summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2006-11-24 19:49:04 +0000
committerMichael Sevakis <jethead71@rockbox.org>2006-11-24 19:49:04 +0000
commit0729b928ce14eafc09efe484bf19df2346880159 (patch)
treea8561f21607bab954580fb8a6b3fafbb33e691c9
parent516d277958019ba27362d5f9fcc5ee70acc87c45 (diff)
downloadrockbox-0729b928ce14eafc09efe484bf19df2346880159.tar.gz
rockbox-0729b928ce14eafc09efe484bf19df2346880159.zip
Recording: Add AIFF recording to SWCODEC. Note: AIFF playback chokes on sample rates other than 44.1kHz whether recorded or created and saved with an external program. Recorded files will still open in an external editor however.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11583 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/Makefile1
-rw-r--r--apps/codecs/SOURCES1
-rw-r--r--apps/codecs/aiff_enc.c408
-rw-r--r--apps/enc_config.c9
-rw-r--r--apps/lang/english.lang15
-rw-r--r--apps/recorder/icons.c3
-rw-r--r--apps/recorder/icons.h1
-rw-r--r--apps/settings.c2
-rw-r--r--apps/settings.h1
-rw-r--r--apps/sound_menu.c1
-rw-r--r--firmware/enc_base.c2
-rw-r--r--firmware/export/enc_base.h8
-rw-r--r--firmware/export/id3.h3
-rw-r--r--firmware/id3.c4
14 files changed, 457 insertions, 2 deletions
diff --git a/apps/codecs/Makefile b/apps/codecs/Makefile
index 12235b490c..38723b7940 100644
--- a/apps/codecs/Makefile
+++ b/apps/codecs/Makefile
@@ -61,6 +61,7 @@ $(OBJDIR)/wavpack.elf : $(OBJDIR)/wavpack.o $(BUILDDIR)/libwavpack.a
61$(OBJDIR)/alac.elf : $(OBJDIR)/alac.o $(BUILDDIR)/libalac.a $(BUILDDIR)/libm4a.a 61$(OBJDIR)/alac.elf : $(OBJDIR)/alac.o $(BUILDDIR)/libalac.a $(BUILDDIR)/libm4a.a
62$(OBJDIR)/aac.elf : $(OBJDIR)/aac.o $(BUILDDIR)/libfaad.a $(BUILDDIR)/libm4a.a 62$(OBJDIR)/aac.elf : $(OBJDIR)/aac.o $(BUILDDIR)/libfaad.a $(BUILDDIR)/libm4a.a
63$(OBJDIR)/shorten.elf : $(OBJDIR)/shorten.o $(BUILDDIR)/libffmpegFLAC.a 63$(OBJDIR)/shorten.elf : $(OBJDIR)/shorten.o $(BUILDDIR)/libffmpegFLAC.a
64$(OBJDIR)/aiff_enc.elf: $(OBJDIR)/aiff_enc.o
64$(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o 65$(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o
65$(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o 66$(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o
66$(OBJDIR)/wavpack_enc.elf: $(OBJDIR)/wavpack_enc.o $(BUILDDIR)/libwavpack.a 67$(OBJDIR)/wavpack_enc.elf: $(OBJDIR)/wavpack_enc.o $(BUILDDIR)/libwavpack.a
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index feadcde0ac..68bb04f926 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -17,6 +17,7 @@ sid.c
17adx.c 17adx.c
18#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 18#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
19/* encoders */ 19/* encoders */
20aiff_enc.c
20mp3_enc.c 21mp3_enc.c
21wav_enc.c 22wav_enc.c
22wavpack_enc.c 23wavpack_enc.c
diff --git a/apps/codecs/aiff_enc.c b/apps/codecs/aiff_enc.c
new file mode 100644
index 0000000000..50c682fa31
--- /dev/null
+++ b/apps/codecs/aiff_enc.c
@@ -0,0 +1,408 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Antonius Hellmann
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef SIMULATOR
21
22#include <inttypes.h>
23#include "codeclib.h"
24
25CODEC_ENC_HEADER
26
27#ifdef USE_IRAM
28extern char iramcopy[];
29extern char iramstart[];
30extern char iramend[];
31extern char iedata[];
32extern char iend[];
33#endif
34
35struct aiff_header
36{
37 uint8_t form_id[4]; /* 00h - 'FORM' */
38 uint32_t form_size; /* 04h - size of file - 8 */
39 uint8_t aiff_id[4]; /* 08h - 'AIFF' */
40 uint8_t comm_id[4]; /* 0Ch - 'COMM' */
41 int32_t comm_size; /* 10h - num_channels through sample_rate
42 (18) */
43 int16_t num_channels; /* 14h - 1=M, 2=S, etc. */
44 uint32_t num_sample_frames; /* 16h - num samples for each channel */
45 int16_t sample_size; /* 1ah - 1-32 bits per sample */
46 uint8_t sample_rate[10]; /* 1ch - IEEE 754 80-bit floating point */
47 uint8_t ssnd_id[4]; /* 26h - "SSND" */
48 int32_t ssnd_size; /* 2ah - size of chunk from offset to
49 end of pcm data */
50 uint32_t offset; /* 2eh - data offset from end of header */
51 uint32_t block_size; /* 32h - pcm data alignment */
52 /* 36h */
53} __attribute__((packed));
54
55#define PCM_DEPTH_BYTES 2
56#define PCM_DEPTH_BITS 16
57#define PCM_SAMP_PER_CHUNK 2048
58#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
59
60/* Template headers */
61struct aiff_header aiff_header =
62{
63 { 'F', 'O', 'R', 'M' }, /* form_id */
64 0, /* form_size (*) */
65 { 'A', 'I', 'F', 'F' }, /* aiff_id */
66 { 'C', 'O', 'M', 'M' }, /* comm_id */
67 H_TO_BE32(18), /* comm_size */
68 0, /* num_channels (*) */
69 0, /* num_sample_frames (*) */
70 H_TO_BE32(PCM_DEPTH_BITS), /* sample_size */
71 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* sample_rate (*) */
72 { 'S', 'S', 'N', 'D' }, /* ssnd_id */
73 0, /* ssnd_size (*) */
74 H_TO_BE32(0), /* offset */
75 H_TO_BE32(0), /* block_size */
76};
77
78/* (*) updated when finalizing file */
79
80static struct codec_api *ci;
81static int num_channels;
82uint32_t sample_rate;
83uint32_t enc_size;
84
85/* convert unsigned 32 bit value to 80-bit floating point number */
86static void uint32_to_ieee754_extended(uint8_t f[10], uint32_t l) ICODE_ATTR;
87static void uint32_to_ieee754_extended(uint8_t f[10], uint32_t l)
88{
89 int32_t exp;
90
91 ci->memset(f, 0, 10);
92
93 if (l == 0)
94 return;
95
96 for (exp = 30; (l & (1ul << 31)) == 0; exp--)
97 l <<= 1;
98
99 /* sign always zero - bit 79 */
100 /* exponent is 0-31 (normalized: 31 - shift + 16383) - bits 64-78 */
101 f[0] = 0x40;
102 f[1] = (uint8_t)exp;
103 /* mantissa is value left justified with most significant non-zero
104 bit stored in bit 63 - bits 0-63 */
105 *(uint32_t *)&f[2] = htobe32(l);
106} /* long_to_ieee754_extended */
107
108/* called version often - inline */
109static inline bool is_file_data_ok(struct enc_file_event_data *data) ICODE_ATTR;
110static inline bool is_file_data_ok(struct enc_file_event_data *data)
111{
112 return data->rec_file >= 0 && (long)data->chunk->flags >= 0;
113} /* is_file_data_ok */
114
115/* called version often - inline */
116static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
117static inline bool on_write_chunk(struct enc_file_event_data *data)
118{
119 if (!is_file_data_ok(data))
120 return false;
121
122 if (data->chunk->enc_data == NULL)
123 {
124#ifdef ROCKBOX_HAS_LOGF
125 ci->logf("aiff enc: NULL data");
126#endif
127 return true;
128 }
129
130 if (ci->write(data->rec_file, data->chunk->enc_data,
131 data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
132 return false;
133
134 data->num_pcm_samples += data->chunk->num_pcm;
135 return true;
136} /* on_write_chunk */
137
138static bool on_start_file(struct enc_file_event_data *data)
139{
140 if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
141 return false;
142
143 data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC);
144
145 if (data->rec_file < 0)
146 return false;
147
148 /* reset sample count */
149 data->num_pcm_samples = 0;
150
151 /* write template headers */
152 if (ci->write(data->rec_file, &aiff_header, sizeof (aiff_header))
153 != sizeof (aiff_header))
154 {
155 return false;
156 }
157
158 data->new_enc_size += sizeof(aiff_header);
159 return true;
160} /* on_start_file */
161
162static bool on_end_file(struct enc_file_event_data *data)
163{
164 /* update template headers */
165 struct aiff_header hdr;
166 uint32_t data_size;
167
168 if (!is_file_data_ok(data))
169 return false;
170
171 if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
172 ci->read(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr))
173 {
174 return false;
175 }
176
177 data_size = data->num_pcm_samples*num_channels*PCM_DEPTH_BYTES;
178
179 /* 'FORM' chunk */
180 hdr.form_size = data_size + sizeof (hdr) - 8;
181
182 /* 'COMM' chunk */
183 hdr.num_channels = htobe16(num_channels);
184 hdr.num_sample_frames = htobe32(data->num_pcm_samples*num_channels/2);
185 uint32_to_ieee754_extended(hdr.sample_rate, sample_rate);
186
187 /* 'SSND' chunk */
188 hdr.ssnd_size = htobe32(data_size + 8);
189
190 if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
191 ci->write(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr))
192 {
193 return false;
194 }
195
196 ci->fsync(data->rec_file);
197 ci->close(data->rec_file);
198 data->rec_file = -1;
199
200 return true;
201} /* on_end_file */
202
203static void enc_events_callback(enum enc_events event, void *data) ICODE_ATTR;
204static void enc_events_callback(enum enc_events event, void *data)
205{
206 if (event == ENC_WRITE_CHUNK)
207 {
208 if (on_write_chunk((struct enc_file_event_data *)data))
209 return;
210 }
211 else if (event == ENC_START_FILE)
212 {
213 if (on_start_file((struct enc_file_event_data *)data))
214 return;
215 }
216 else if (event == ENC_END_FILE)
217 {
218 if (on_end_file((struct enc_file_event_data *)data))
219 return;
220 }
221 else
222 {
223 return;
224 }
225
226 ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
227} /* enc_events_callback */
228
229/* convert native pcm samples to aiff format samples */
230static void chunk_to_aiff_format(uint32_t *src, uint32_t *dst) ICODE_ATTR;
231static void chunk_to_aiff_format(uint32_t *src, uint32_t *dst)
232{
233 if (num_channels == 1)
234 {
235 /* On big endian:
236 * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
237 * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
238 * |MMMMMMMMmmmmmmmm|MMMMMMMMmmmmmmmm|
239 *
240 * On little endian:
241 * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
242 * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
243 * |MMMMMMMMmmmmmmmm|MMMMMMMMmmmmmmmm|
244 */
245 uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
246
247 inline void to_mono(uint32_t **src, uint32_t **dst)
248 {
249 int32_t lr1, lr2;
250
251 lr1 = *(*src)++;
252 lr1 = ((int16_t)lr1 + (lr1 >> 16)) >> 1;
253
254 lr2 = *(*src)++;
255 lr2 = ((int16_t)lr2 + (lr2 >> 16)) >> 1;
256 *(*dst)++ = swap_odd_even_le32((lr1 << 16) | (uint16_t)lr2);
257 } /* to_mono */
258
259 do
260 {
261 to_mono(&src, &dst);
262 to_mono(&src, &dst);
263 to_mono(&src, &dst);
264 to_mono(&src, &dst);
265 to_mono(&src, &dst);
266 to_mono(&src, &dst);
267 to_mono(&src, &dst);
268 to_mono(&src, &dst);
269 }
270 while (src < src_end);
271 }
272 else
273 {
274#ifdef ROCKBOX_BIG_ENDIAN
275 /* |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
276 * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
277 */
278 ci->memcpy(dst, src, PCM_CHUNK_SIZE);
279#else
280 /* |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
281 * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
282 */
283 uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
284
285 do
286 {
287 *dst++ = swap_odd_even32(*src++);
288 *dst++ = swap_odd_even32(*src++);
289 *dst++ = swap_odd_even32(*src++);
290 *dst++ = swap_odd_even32(*src++);
291 *dst++ = swap_odd_even32(*src++);
292 *dst++ = swap_odd_even32(*src++);
293 *dst++ = swap_odd_even32(*src++);
294 *dst++ = swap_odd_even32(*src++);
295 }
296 while (src < src_end);
297#endif
298 }
299} /* chunk_to_aiff_format */
300
301static bool init_encoder(void)
302{
303 struct enc_inputs inputs;
304 struct enc_parameters params;
305
306 if (ci->enc_get_inputs == NULL ||
307 ci->enc_set_parameters == NULL ||
308 ci->enc_get_chunk == NULL ||
309 ci->enc_finish_chunk == NULL ||
310 ci->enc_pcm_buf_near_empty == NULL ||
311 ci->enc_get_pcm_data == NULL )
312 return false;
313
314 ci->enc_get_inputs(&inputs);
315
316 if (inputs.config->afmt != AFMT_AIFF)
317 return false;
318
319 sample_rate = inputs.sample_rate;
320 num_channels = inputs.num_channels;
321
322 /* configure the buffer system */
323 params.afmt = AFMT_AIFF;
324 enc_size = PCM_CHUNK_SIZE*inputs.num_channels / 2;
325 params.chunk_size = enc_size;
326 params.enc_sample_rate = sample_rate;
327 params.reserve_bytes = 0;
328 params.events_callback = enc_events_callback;
329 ci->enc_set_parameters(&params);
330
331 return true;
332} /* init_encoder */
333
334/* main codec entry point */
335enum codec_status codec_start(struct codec_api* api)
336{
337 bool cpu_boosted;
338
339 ci = api; /* copy to global api pointer */
340
341#ifdef USE_IRAM
342 ci->memcpy(iramstart, iramcopy, iramend - iramstart);
343 ci->memset(iedata, 0, iend - iedata);
344#endif
345
346 if (!init_encoder())
347 {
348 ci->enc_codec_loaded = -1;
349 return CODEC_ERROR;
350 }
351
352 /* main application waits for this flag during encoder loading */
353 ci->enc_codec_loaded = 1;
354
355 ci->cpu_boost(true);
356 cpu_boosted = true;
357
358 /* main encoding loop */
359 while(!ci->stop_codec)
360 {
361 uint32_t *src;
362
363 while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL)
364 {
365 struct enc_chunk_hdr *chunk;
366
367 if (ci->stop_codec)
368 break;
369
370 if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
371 {
372 ci->cpu_boost(true);
373 cpu_boosted = true;
374 }
375
376 chunk = ci->enc_get_chunk();
377 chunk->enc_size = enc_size;
378 chunk->num_pcm = PCM_SAMP_PER_CHUNK;
379 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
380
381 chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data);
382
383 ci->enc_finish_chunk();
384 ci->yield();
385 }
386
387 if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
388 {
389 ci->cpu_boost(false);
390 cpu_boosted = false;
391 }
392
393 ci->yield();
394 }
395
396 if (cpu_boosted) /* set initial boost state */
397 ci->cpu_boost(false);
398
399 /* reset parameters to initial state */
400 ci->enc_set_parameters(NULL);
401
402 /* main application waits for this flag during encoder removing */
403 ci->enc_codec_loaded = 0;
404
405 return CODEC_OK;
406} /* codec_start */
407
408#endif /* ndef SIMULATOR */
diff --git a/apps/enc_config.c b/apps/enc_config.c
index 384e679c42..2d2abae61a 100644
--- a/apps/enc_config.c
+++ b/apps/enc_config.c
@@ -49,6 +49,8 @@ static bool enc_no_config_menu(struct encoder_config *cfg);
49/** Function definitions for each codec - add these to enc_data 49/** Function definitions for each codec - add these to enc_data
50 list following the definitions **/ 50 list following the definitions **/
51 51
52/** aiff_enc.codec **/
53
52/** mp3_enc.codec **/ 54/** mp3_enc.codec **/
53/* mp3_enc: return encoder capabilities */ 55/* mp3_enc: return encoder capabilities */
54static void mp3_enc_get_caps(const struct encoder_config *cfg, 56static void mp3_enc_get_caps(const struct encoder_config *cfg,
@@ -209,6 +211,13 @@ static const struct encoder_data
209 bool (*menu)(struct encoder_config *); 211 bool (*menu)(struct encoder_config *);
210} enc_data[REC_NUM_FORMATS] = 212} enc_data[REC_NUM_FORMATS] =
211{ 213{
214 /* aiff_enc.codec */
215 [REC_FORMAT_AIFF] = {
216 NULL,
217 NULL,
218 NULL,
219 enc_no_config_menu,
220 },
212 /* mp3_enc.codec */ 221 /* mp3_enc.codec */
213 [REC_FORMAT_MPA_L3] = { 222 [REC_FORMAT_MPA_L3] = {
214 mp3_enc_get_caps, 223 mp3_enc_get_caps,
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index f3603e951b..a306138356 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -10266,3 +10266,18 @@
10266 *: "" 10266 *: ""
10267 </voice> 10267 </voice>
10268</phrase> 10268</phrase>
10269<phrase>
10270 id: LANG_AFMT_AIFF
10271 desc: audio format description
10272 user:
10273 <source>
10274 *: "AIFF"
10275 </source>
10276 <dest>
10277 *: "AIFF"
10278 </dest>
10279 <voice>
10280 *: "AIFF"
10281 </voice>
10282</phrase>
10283
diff --git a/apps/recorder/icons.c b/apps/recorder/icons.c
index ba22bb5a2c..4e1496e721 100644
--- a/apps/recorder/icons.c
+++ b/apps/recorder/icons.c
@@ -121,6 +121,9 @@ const unsigned char bitmap_formats_18x8[Format_18x8Last][18]=
121 [0 ... Format_18x8Last-1] = /* auto-blank */ 121 [0 ... Format_18x8Last-1] = /* auto-blank */
122 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 122 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ___ */ 123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ___ */
124 [Format_18x8_AIFF] =
125 {0x00, 0x3c, 0x0a, 0x0a, 0x0a, 0x3c, 0x00, 0x3e, 0x00,
126 0x3e, 0x0a, 0x02, 0x02, 0x00, 0x3e, 0x0a, 0x02, 0x02}, /* AIFF */
124 [Format_18x8_MPA_L3] = 127 [Format_18x8_MPA_L3] =
125 {0x00, 0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00, 128 {0x00, 0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* M__ */ 129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* M__ */
diff --git a/apps/recorder/icons.h b/apps/recorder/icons.h
index 1e7b8dba1e..5aec0730c6 100644
--- a/apps/recorder/icons.h
+++ b/apps/recorder/icons.h
@@ -111,6 +111,7 @@ extern const unsigned char bitmap_glyphs_4x8[Glyph_4x8Last][4];
111#ifdef ID3_H 111#ifdef ID3_H
112/* This enum is redundant but sort of in keeping with the style */ 112/* This enum is redundant but sort of in keeping with the style */
113enum rec_format_18x8 { 113enum rec_format_18x8 {
114 Format_18x8_AIFF = REC_FORMAT_AIFF,
114 Format_18x8_MPA_L3 = REC_FORMAT_MPA_L3, 115 Format_18x8_MPA_L3 = REC_FORMAT_MPA_L3,
115 Format_18x8_WAVPACK = REC_FORMAT_WAVPACK, 116 Format_18x8_WAVPACK = REC_FORMAT_WAVPACK,
116 Format_18x8_PCM_WAV = REC_FORMAT_PCM_WAV, 117 Format_18x8_PCM_WAV = REC_FORMAT_PCM_WAV,
diff --git a/apps/settings.c b/apps/settings.c
index fc0e5248a3..94d456fcf5 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -533,6 +533,8 @@ static const struct bit_entry hd_bits[] =
533 {REC_FORMAT_CFG_NUM_BITS ,S_O(rec_format), REC_FORMAT_DEFAULT, 533 {REC_FORMAT_CFG_NUM_BITS ,S_O(rec_format), REC_FORMAT_DEFAULT,
534 "rec format", REC_FORMAT_CFG_VAL_LIST }, 534 "rec format", REC_FORMAT_CFG_VAL_LIST },
535 /** Encoder settings start - keep these together **/ 535 /** Encoder settings start - keep these together **/
536 /* aiff_enc */
537 /* (no settings yet) */
536 /* mp3_enc */ 538 /* mp3_enc */
537 {5,S_O(mp3_enc_config.bitrate), MP3_ENC_BITRATE_CFG_DEFAULT, 539 {5,S_O(mp3_enc_config.bitrate), MP3_ENC_BITRATE_CFG_DEFAULT,
538 "mp3_enc bitrate", MP3_ENC_BITRATE_CFG_VALUE_LIST }, 540 "mp3_enc bitrate", MP3_ENC_BITRATE_CFG_VALUE_LIST },
diff --git a/apps/settings.h b/apps/settings.h
index c0c6a943ce..cb57c1ac77 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -528,6 +528,7 @@ struct user_settings
528 struct mp3_enc_config mp3_enc_config; 528 struct mp3_enc_config mp3_enc_config;
529#if 0 /* These currently contain no members but their places in line 529#if 0 /* These currently contain no members but their places in line
530 should be held */ 530 should be held */
531 struct aiff_enc_config aiff_enc_config;
531 struct wav_enc_config wav_enc_config; 532 struct wav_enc_config wav_enc_config;
532 struct wavpack_enc_config wavpack_enc_config; 533 struct wavpack_enc_config wavpack_enc_config;
533#endif 534#endif
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index bcc9163893..52a6c3b34c 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -363,6 +363,7 @@ void make_options_from_indexes(const struct opt_items *src_names,
363static bool recformat(void) 363static bool recformat(void)
364{ 364{
365 static const struct opt_items names[REC_NUM_FORMATS] = { 365 static const struct opt_items names[REC_NUM_FORMATS] = {
366 [REC_FORMAT_AIFF] = { STR(LANG_AFMT_AIFF) },
366 [REC_FORMAT_MPA_L3] = { STR(LANG_AFMT_MPA_L3) }, 367 [REC_FORMAT_MPA_L3] = { STR(LANG_AFMT_MPA_L3) },
367 [REC_FORMAT_WAVPACK] = { STR(LANG_AFMT_WAVPACK) }, 368 [REC_FORMAT_WAVPACK] = { STR(LANG_AFMT_WAVPACK) },
368 [REC_FORMAT_PCM_WAV] = { STR(LANG_AFMT_PCM_WAV) }, 369 [REC_FORMAT_PCM_WAV] = { STR(LANG_AFMT_PCM_WAV) },
diff --git a/firmware/enc_base.c b/firmware/enc_base.c
index e346064fe2..6cd421142c 100644
--- a/firmware/enc_base.c
+++ b/firmware/enc_base.c
@@ -19,6 +19,8 @@
19#include "config.h" 19#include "config.h"
20#include "audio.h" 20#include "audio.h"
21 21
22/** aiff_enc.codec **/
23
22/** mp3_enc.codec **/ 24/** mp3_enc.codec **/
23 25
24/* These are in descending order rather than in MPEG frequency index 26/* These are in descending order rather than in MPEG frequency index
diff --git a/firmware/export/enc_base.h b/firmware/export/enc_base.h
index 85101ac7fd..1be796ec8f 100644
--- a/firmware/export/enc_base.h
+++ b/firmware/export/enc_base.h
@@ -24,6 +24,14 @@
24 24
25/** encoder config structures **/ 25/** encoder config structures **/
26 26
27/** aiff_enc.codec **/
28struct aiff_enc_config
29{
30#if 0
31 unsigned long sample_depth;
32#endif
33};
34
27/** mp3_enc.codec **/ 35/** mp3_enc.codec **/
28#define MP3_BITR_CAP_8 (1 << 0) 36#define MP3_BITR_CAP_8 (1 << 0)
29#define MP3_BITR_CAP_16 (1 << 1) 37#define MP3_BITR_CAP_16 (1 << 1)
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 3d24e2006e..b099aed716 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -78,6 +78,7 @@ enum rec_format_indexes
78 /* start formats */ 78 /* start formats */
79 79
80 REC_FORMAT_PCM_WAV, 80 REC_FORMAT_PCM_WAV,
81 REC_FORMAT_AIFF,
81 REC_FORMAT_WAVPACK, 82 REC_FORMAT_WAVPACK,
82 REC_FORMAT_MPA_L3, 83 REC_FORMAT_MPA_L3,
83 84
@@ -93,7 +94,7 @@ enum rec_format_indexes
93 REC_FORMAT_CFG_NUM_BITS = 2 94 REC_FORMAT_CFG_NUM_BITS = 2
94}; 95};
95 96
96#define REC_FORMAT_CFG_VAL_LIST "wave,wvpk,mpa3" 97#define REC_FORMAT_CFG_VAL_LIST "aiff,wave,wvpk,mpa3"
97 98
98/* get REC_FORMAT_* corresponding AFMT_* */ 99/* get REC_FORMAT_* corresponding AFMT_* */
99extern const int rec_format_afmt[REC_NUM_FORMATS]; 100extern const int rec_format_afmt[REC_NUM_FORMATS];
diff --git a/firmware/id3.c b/firmware/id3.c
index 90b5b3bdee..74cea7f037 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -64,7 +64,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
64#if CONFIG_CODEC == SWCODEC 64#if CONFIG_CODEC == SWCODEC
65 /* Audio Interchange File Format */ 65 /* Audio Interchange File Format */
66 [AFMT_AIFF] = 66 [AFMT_AIFF] =
67 AFMT_ENTRY("AIFF", "aiff", NULL, "aiff\0aif\0"), 67 AFMT_ENTRY("AIFF", "aiff", "aiff_enc", "aiff\0aif\0"),
68 /* Uncompressed PCM in a WAV file */ 68 /* Uncompressed PCM in a WAV file */
69 [AFMT_PCM_WAV] = 69 [AFMT_PCM_WAV] =
70 AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ), 70 AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ),
@@ -108,6 +108,7 @@ const int rec_format_afmt[REC_NUM_FORMATS] =
108 /* give AFMT_UNKNOWN by default */ 108 /* give AFMT_UNKNOWN by default */
109 [0 ... REC_NUM_FORMATS-1] = AFMT_UNKNOWN, 109 [0 ... REC_NUM_FORMATS-1] = AFMT_UNKNOWN,
110 /* add new entries below this line */ 110 /* add new entries below this line */
111 [REC_FORMAT_AIFF] = AFMT_AIFF,
111 [REC_FORMAT_MPA_L3] = AFMT_MPA_L3, 112 [REC_FORMAT_MPA_L3] = AFMT_MPA_L3,
112 [REC_FORMAT_WAVPACK] = AFMT_WAVPACK, 113 [REC_FORMAT_WAVPACK] = AFMT_WAVPACK,
113 [REC_FORMAT_PCM_WAV] = AFMT_PCM_WAV, 114 [REC_FORMAT_PCM_WAV] = AFMT_PCM_WAV,
@@ -119,6 +120,7 @@ const int afmt_rec_format[AFMT_NUM_CODECS] =
119 /* give -1 by default */ 120 /* give -1 by default */
120 [0 ... AFMT_NUM_CODECS-1] = -1, 121 [0 ... AFMT_NUM_CODECS-1] = -1,
121 /* add new entries below this line */ 122 /* add new entries below this line */
123 [AFMT_AIFF] = REC_FORMAT_AIFF,
122 [AFMT_MPA_L3] = REC_FORMAT_MPA_L3, 124 [AFMT_MPA_L3] = REC_FORMAT_MPA_L3,
123 [AFMT_WAVPACK] = REC_FORMAT_WAVPACK, 125 [AFMT_WAVPACK] = REC_FORMAT_WAVPACK,
124 [AFMT_PCM_WAV] = REC_FORMAT_PCM_WAV, 126 [AFMT_PCM_WAV] = REC_FORMAT_PCM_WAV,