summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES3
-rw-r--r--apps/codecs.c25
-rw-r--r--apps/codecs.h64
-rw-r--r--apps/codecs/libwavpack/bits.c22
-rw-r--r--apps/codecs/mp3_enc.c1182
-rw-r--r--apps/codecs/wav_enc.c419
-rw-r--r--apps/codecs/wavpack_enc.c539
-rw-r--r--apps/eq_menu.c3
-rw-r--r--apps/gui/statusbar.c196
-rw-r--r--apps/lang/english.lang114
-rw-r--r--apps/main.c3
-rw-r--r--apps/metadata.c48
-rw-r--r--apps/misc.c57
-rw-r--r--apps/misc.h35
-rw-r--r--apps/pcmbuf.c27
-rw-r--r--apps/pcmbuf.h2
-rw-r--r--apps/playback.c262
-rw-r--r--apps/playlist.c12
-rw-r--r--apps/plugin.c8
-rw-r--r--apps/recorder/icons.c90
-rw-r--r--apps/recorder/icons.h60
-rw-r--r--apps/recorder/peakmeter.c6
-rw-r--r--apps/recorder/radio.c25
-rw-r--r--apps/recorder/recording.c250
-rw-r--r--apps/recorder/recording.h13
-rw-r--r--apps/settings.c44
-rw-r--r--apps/settings.h34
-rw-r--r--apps/sound_menu.c288
-rw-r--r--apps/status.c6
-rw-r--r--apps/talk.c27
-rw-r--r--apps/tree.c2
-rw-r--r--bootloader/main.c4
-rw-r--r--firmware/SOURCES26
-rw-r--r--firmware/drivers/tlv320.c45
-rw-r--r--firmware/drivers/uda1380.c84
-rw-r--r--firmware/export/audio.h106
-rw-r--r--firmware/export/config-h100.h6
-rw-r--r--firmware/export/config-h120.h6
-rw-r--r--firmware/export/config-h300.h7
-rw-r--r--firmware/export/config-iaudiox5.h6
-rw-r--r--firmware/export/id3.h91
-rw-r--r--firmware/export/pcm_playback.h16
-rw-r--r--firmware/export/pcm_record.h46
-rw-r--r--firmware/export/system.h81
-rw-r--r--firmware/export/thread.h3
-rw-r--r--firmware/export/tlv320.h10
-rw-r--r--firmware/export/uda1380.h13
-rw-r--r--firmware/id3.c138
-rw-r--r--firmware/mpeg.c20
-rw-r--r--firmware/pcm_playback.c700
-rw-r--r--firmware/pcm_record.c2002
-rw-r--r--firmware/system.c3
-rw-r--r--firmware/target/coldfire/iaudio/x5/system-x5.c7
-rw-r--r--firmware/target/coldfire/iriver/system-iriver.c7
-rw-r--r--firmware/target/coldfire/system-coldfire.c7
-rw-r--r--firmware/target/coldfire/system-target.h29
-rw-r--r--firmware/thread.c8
-rw-r--r--uisimulator/sdl/lcd-charcell.c3
58 files changed, 4664 insertions, 2676 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index e1d8e7bbdd..ccfc7fa280 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -73,6 +73,9 @@ pcmbuf.c
73playback.c 73playback.c
74codecs.c 74codecs.c
75dsp.c 75dsp.c
76#ifdef HAVE_RECORDING
77enc_config.c
78#endif
76eq.c 79eq.c
77#if defined(CPU_COLDFIRE) && !defined(SIMULATOR) 80#if defined(CPU_COLDFIRE) && !defined(SIMULATOR)
78dsp_cf.S 81dsp_cf.S
diff --git a/apps/codecs.c b/apps/codecs.c
index f33957eba2..4491dadf49 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -50,6 +50,7 @@
50#include "sound.h" 50#include "sound.h"
51#include "database.h" 51#include "database.h"
52#include "splash.h" 52#include "splash.h"
53#include "general.h"
53 54
54#ifdef SIMULATOR 55#ifdef SIMULATOR
55#if CONFIG_CODEC == SWCODEC 56#if CONFIG_CODEC == SWCODEC
@@ -104,6 +105,7 @@ struct codec_api ci = {
104 PREFIX(remove), 105 PREFIX(remove),
105 PREFIX(rename), 106 PREFIX(rename),
106 PREFIX(ftruncate), 107 PREFIX(ftruncate),
108 PREFIX(fsync),
107 fdprintf, 109 fdprintf,
108 read_line, 110 read_line,
109 settings_parseline, 111 settings_parseline,
@@ -187,6 +189,7 @@ struct codec_api ci = {
187 get_time, 189 get_time,
188 set_time, 190 set_time,
189 plugin_get_audio_buffer, 191 plugin_get_audio_buffer,
192 round_value_to_list32,
190 193
191#if defined(DEBUG) || defined(SIMULATOR) 194#if defined(DEBUG) || defined(SIMULATOR)
192 debugf, 195 debugf,
@@ -213,11 +216,11 @@ struct codec_api ci = {
213 false, 216 false,
214 enc_get_inputs, 217 enc_get_inputs,
215 enc_set_parameters, 218 enc_set_parameters,
216 enc_alloc_chunk, 219 enc_get_chunk,
217 enc_free_chunk, 220 enc_finish_chunk,
218 enc_wavbuf_near_empty, 221 enc_pcm_buf_near_empty,
219 enc_get_wav_data, 222 enc_get_pcm_data,
220 &enc_set_header_callback, 223 enc_unget_pcm_data
221#endif 224#endif
222 225
223 /* new stuff at the end, sort into place next time 226 /* new stuff at the end, sort into place next time
@@ -225,10 +228,10 @@ struct codec_api ci = {
225 228
226}; 229};
227 230
228void codec_get_full_path(char *path, const char *codec_fn) 231void codec_get_full_path(char *path, const char *codec_root_fn)
229{ 232{
230 /* Create full codec path */ 233 snprintf(path, MAX_PATH-1, CODECS_DIR "/%s." CODEC_EXTENSION,
231 snprintf(path, MAX_PATH-1, CODECS_DIR "/%s", codec_fn); 234 codec_root_fn);
232} 235}
233 236
234int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, 237int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
@@ -254,7 +257,11 @@ int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
254 hdr = (struct codec_header *)codecbuf; 257 hdr = (struct codec_header *)codecbuf;
255 258
256 if (size <= (signed)sizeof(struct codec_header) 259 if (size <= (signed)sizeof(struct codec_header)
257 || hdr->magic != CODEC_MAGIC 260 || (hdr->magic != CODEC_MAGIC
261#ifdef HAVE_RECORDING
262 && hdr->magic != CODEC_ENC_MAGIC
263#endif
264 )
258 || hdr->target_id != TARGET_ID 265 || hdr->target_id != TARGET_ID
259 || hdr->load_addr != codecbuf 266 || hdr->load_addr != codecbuf
260 || hdr->end_addr > codecbuf + CODEC_SIZE) 267 || hdr->end_addr > codecbuf + CODEC_SIZE)
diff --git a/apps/codecs.h b/apps/codecs.h
index 96804a889b..0b90ef9c19 100644
--- a/apps/codecs.h
+++ b/apps/codecs.h
@@ -46,7 +46,7 @@
46#include "profile.h" 46#include "profile.h"
47#endif 47#endif
48#if (CONFIG_CODEC == SWCODEC) 48#if (CONFIG_CODEC == SWCODEC)
49#if !defined(SIMULATOR) 49#if !defined(SIMULATOR) && defined(HAVE_RECORDING)
50#include "pcm_record.h" 50#include "pcm_record.h"
51#endif 51#endif
52#include "dsp.h" 52#include "dsp.h"
@@ -84,15 +84,18 @@
84#define PREFIX(_x_) _x_ 84#define PREFIX(_x_) _x_
85#endif 85#endif
86 86
87/* magic for normal codecs */
87#define CODEC_MAGIC 0x52434F44 /* RCOD */ 88#define CODEC_MAGIC 0x52434F44 /* RCOD */
89/* magic for encoder codecs */
90#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
88 91
89/* increase this every time the api struct changes */ 92/* increase this every time the api struct changes */
90#define CODEC_API_VERSION 9 93#define CODEC_API_VERSION 10
91 94
92/* update this to latest version if a change to the api struct breaks 95/* update this to latest version if a change to the api struct breaks
93 backwards compatibility (and please take the opportunity to sort in any 96 backwards compatibility (and please take the opportunity to sort in any
94 new function which are "waiting" at the end of the function table) */ 97 new function which are "waiting" at the end of the function table) */
95#define CODEC_MIN_API_VERSION 8 98#define CODEC_MIN_API_VERSION 10
96 99
97/* codec return codes */ 100/* codec return codes */
98enum codec_status { 101enum codec_status {
@@ -176,6 +179,7 @@ struct codec_api {
176 int (*PREFIX(remove))(const char* pathname); 179 int (*PREFIX(remove))(const char* pathname);
177 int (*PREFIX(rename))(const char* path, const char* newname); 180 int (*PREFIX(rename))(const char* path, const char* newname);
178 int (*PREFIX(ftruncate))(int fd, off_t length); 181 int (*PREFIX(ftruncate))(int fd, off_t length);
182 int (*PREFIX(fsync))(int fd);
179 183
180 int (*fdprintf)(int fd, const char *fmt, ...); 184 int (*fdprintf)(int fd, const char *fmt, ...);
181 int (*read_line)(int fd, char* buffer, int buffer_size); 185 int (*read_line)(int fd, char* buffer, int buffer_size);
@@ -232,7 +236,8 @@ struct codec_api {
232 /* sound */ 236 /* sound */
233 void (*sound_set)(int setting, int value); 237 void (*sound_set)(int setting, int value);
234#ifndef SIMULATOR 238#ifndef SIMULATOR
235 void (*mp3_play_data)(const unsigned char* start, int size, void (*get_more)(unsigned char** start, int* size)); 239 void (*mp3_play_data)(const unsigned char* start,
240 int size, void (*get_more)(unsigned char** start, int* size));
236 void (*mp3_play_pause)(bool play); 241 void (*mp3_play_pause)(bool play);
237 void (*mp3_play_stop)(void); 242 void (*mp3_play_stop)(void);
238 bool (*mp3_is_playing)(void); 243 bool (*mp3_is_playing)(void);
@@ -263,6 +268,10 @@ struct codec_api {
263 struct tm* (*get_time)(void); 268 struct tm* (*get_time)(void);
264 int (*set_time)(const struct tm *tm); 269 int (*set_time)(const struct tm *tm);
265 void* (*plugin_get_audio_buffer)(int* buffer_size); 270 void* (*plugin_get_audio_buffer)(int* buffer_size);
271 int (*round_value_to_list32)(unsigned long value,
272 const unsigned long list[],
273 int count,
274 bool signd);
266 275
267#if defined(DEBUG) || defined(SIMULATOR) 276#if defined(DEBUG) || defined(SIMULATOR)
268 void (*debugf)(const char *fmt, ...); 277 void (*debugf)(const char *fmt, ...);
@@ -291,18 +300,14 @@ struct codec_api {
291#endif 300#endif
292 301
293#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 302#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
294 bool enc_codec_loaded; 303 volatile int enc_codec_loaded; /* <0=error, 0=pending, >0=ok */
295 void (*enc_get_inputs)(int *buffer_size, 304 void (*enc_get_inputs)(struct enc_inputs *inputs);
296 int *channels, int *quality); 305 void (*enc_set_parameters)(struct enc_parameters *params);
297 void (*enc_set_parameters)(int chunk_size, int num_chunks, 306 struct enc_chunk_hdr * (*enc_get_chunk)(void);
298 int samp_per_chunk, char *head_ptr, int head_size, 307 void (*enc_finish_chunk)(void);
299 int enc_id); 308 int (*enc_pcm_buf_near_empty)(void);
300 unsigned int* (*enc_alloc_chunk)(void); 309 unsigned char * (*enc_get_pcm_data)(size_t size);
301 void (*enc_free_chunk)(void); 310 size_t (*enc_unget_pcm_data)(size_t size);
302 int (*enc_wavbuf_near_empty)(void);
303 char* (*enc_get_wav_data)(int size);
304 void (**enc_set_header_callback)(void *head_buffer,
305 int head_size, int num_samples, bool is_file_header);
306#endif 311#endif
307 312
308 /* new stuff at the end, sort into place next time 313 /* new stuff at the end, sort into place next time
@@ -312,34 +317,49 @@ struct codec_api {
312 317
313/* codec header */ 318/* codec header */
314struct codec_header { 319struct codec_header {
315 unsigned long magic; 320 unsigned long magic; /* RCOD or RENC */
316 unsigned short target_id; 321 unsigned short target_id;
317 unsigned short api_version; 322 unsigned short api_version;
318 unsigned char *load_addr; 323 unsigned char *load_addr;
319 unsigned char *end_addr; 324 unsigned char *end_addr;
320 enum codec_status(*entry_point)(struct codec_api*); 325 enum codec_status(*entry_point)(struct codec_api*);
321}; 326};
327
322#ifdef CODEC 328#ifdef CODEC
323#ifndef SIMULATOR 329#ifndef SIMULATOR
324/* plugin_* is correct, codecs use the plugin linker script */ 330/* plugin_* is correct, codecs use the plugin linker script */
325extern unsigned char plugin_start_addr[]; 331extern unsigned char plugin_start_addr[];
326extern unsigned char plugin_end_addr[]; 332extern unsigned char plugin_end_addr[];
333/* decoders */
327#define CODEC_HEADER \ 334#define CODEC_HEADER \
328 const struct codec_header __header \ 335 const struct codec_header __header \
329 __attribute__ ((section (".header")))= { \ 336 __attribute__ ((section (".header")))= { \
330 CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ 337 CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
331 plugin_start_addr, plugin_end_addr, codec_start }; 338 plugin_start_addr, plugin_end_addr, codec_start };
332#else /* SIMULATOR */ 339/* encoders */
340#define CODEC_ENC_HEADER \
341 const struct codec_header __header \
342 __attribute__ ((section (".header")))= { \
343 CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
344 plugin_start_addr, plugin_end_addr, codec_start };
345
346#else /* def SIMULATOR */
347/* decoders */
333#define CODEC_HEADER \ 348#define CODEC_HEADER \
334 const struct codec_header __header = { \ 349 const struct codec_header __header = { \
335 CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \ 350 CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
336 NULL, NULL, codec_start }; 351 NULL, NULL, codec_start };
337#endif 352/* encoders */
338#endif 353#define CODEC_ENC_HEADER \
354 const struct codec_header __header = { \
355 CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
356 NULL, NULL, codec_start };
357#endif /* SIMULATOR */
358#endif /* CODEC */
339 359
340/* create full codec path from filenames in audio_formats[] 360/* create full codec path from root filenames in audio_formats[]
341 assumes buffer size is MAX_PATH */ 361 assumes buffer size is MAX_PATH */
342void codec_get_full_path(char *path, const char *codec_fn); 362void codec_get_full_path(char *path, const char *codec_root_fn);
343 363
344/* defined by the codec loader (codec.c) */ 364/* defined by the codec loader (codec.c) */
345int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap, 365int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
diff --git a/apps/codecs/libwavpack/bits.c b/apps/codecs/libwavpack/bits.c
index 0a148e123f..0f0e79c292 100644
--- a/apps/codecs/libwavpack/bits.c
+++ b/apps/codecs/libwavpack/bits.c
@@ -15,6 +15,7 @@
15// the malloc() system is provided. 15// the malloc() system is provided.
16 16
17#include "wavpack.h" 17#include "wavpack.h"
18#include "system.h"
18 19
19#include <string.h> 20#include <string.h>
20 21
@@ -118,19 +119,16 @@ uint32_t bs_close_write (Bitstream *bs)
118void little_endian_to_native (void *data, char *format) 119void little_endian_to_native (void *data, char *format)
119{ 120{
120 uchar *cp = (uchar *) data; 121 uchar *cp = (uchar *) data;
121 int32_t temp;
122 122
123 while (*format) { 123 while (*format) {
124 switch (*format) { 124 switch (*format) {
125 case 'L': 125 case 'L':
126 temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int32_t) cp [3] << 24); 126 *(long *)cp = letoh32(*(long *)cp);
127 * (int32_t *) cp = temp;
128 cp += 4; 127 cp += 4;
129 break; 128 break;
130 129
131 case 'S': 130 case 'S':
132 temp = cp [0] + (cp [1] << 8); 131 *(short *)cp = letoh16(*(short *)cp);
133 * (short *) cp = (short) temp;
134 cp += 2; 132 cp += 2;
135 break; 133 break;
136 134
@@ -148,28 +146,22 @@ void little_endian_to_native (void *data, char *format)
148void native_to_little_endian (void *data, char *format) 146void native_to_little_endian (void *data, char *format)
149{ 147{
150 uchar *cp = (uchar *) data; 148 uchar *cp = (uchar *) data;
151 int32_t temp;
152 149
153 while (*format) { 150 while (*format) {
154 switch (*format) { 151 switch (*format) {
155 case 'L': 152 case 'L':
156 temp = * (int32_t *) cp; 153 *(long *)cp = htole32(*(long *)cp);
157 *cp++ = (uchar) temp; 154 cp += 4;
158 *cp++ = (uchar) (temp >> 8);
159 *cp++ = (uchar) (temp >> 16);
160 *cp++ = (uchar) (temp >> 24);
161 break; 155 break;
162 156
163 case 'S': 157 case 'S':
164 temp = * (short *) cp; 158 *(short *)cp = htole16(*(short *)cp);
165 *cp++ = (uchar) temp; 159 cp += 2;
166 *cp++ = (uchar) (temp >> 8);
167 break; 160 break;
168 161
169 default: 162 default:
170 if (*format >= '0' && *format <= '9') 163 if (*format >= '0' && *format <= '9')
171 cp += *format - '0'; 164 cp += *format - '0';
172
173 break; 165 break;
174 } 166 }
175 167
diff --git a/apps/codecs/mp3_enc.c b/apps/codecs/mp3_enc.c
index 3caca94f35..cb727ce01e 100644
--- a/apps/codecs/mp3_enc.c
+++ b/apps/codecs/mp3_enc.c
@@ -32,20 +32,19 @@
32 32
33#ifndef SIMULATOR 33#ifndef SIMULATOR
34 34
35#include <inttypes.h>
35#include "codeclib.h" 36#include "codeclib.h"
36 37
37CODEC_HEADER 38CODEC_ENC_HEADER
38 39
39#ifdef USE_IRAM 40#define ENC_PADDING_FRAMES1 2
40extern char iramcopy[]; 41#define ENC_PADDING_FRAMES2 4
41extern char iramstart[]; 42#define ENC_DELAY_SAMP 576
42extern char iramend[]; 43#define ENC_DELAY_SIZE (ENC_DELAY_SAMP*4)
43extern char iedata[]; 44#define SAMP_PER_FRAME1 1152
44extern char iend[]; 45#define SAMP_PER_FRAME2 576
45#endif 46#define PCM_CHUNK_SIZE1 (SAMP_PER_FRAME1*4)
46 47#define PCM_CHUNK_SIZE2 (SAMP_PER_FRAME2*4)
47
48#define SAMP_PER_FRAME 1152
49#define SAMPL2 576 48#define SAMPL2 576
50#define SBLIMIT 32 49#define SBLIMIT 32
51#define HTN 16 50#define HTN 16
@@ -54,15 +53,16 @@ extern char iend[];
54#define putlong(c, s) if(s+sz <= 32) { cc = (cc << s) | c; sz+= s; } \ 53#define putlong(c, s) if(s+sz <= 32) { cc = (cc << s) | c; sz+= s; } \
55 else { putbits(cc, sz); cc = c; sz = s; } 54 else { putbits(cc, sz); cc = c; sz = s; }
56 55
57enum e_byte_order { order_unknown, order_bigEndian, order_littleEndian }; 56#ifdef USE_IRAM
58 57extern char iramcopy[];
59typedef unsigned long uint32; 58extern char iramstart[];
60typedef unsigned short uint16; 59extern char iramend[];
61typedef unsigned char uint8; 60extern char iedata[];
62 61extern char iend[];
62#endif
63 63
64typedef struct { 64typedef struct {
65 int type; /* 0=(22.05,24,16kHz) 1=(44.1,48,32kHz) */ 65 int type; /* 0=(MPEG2 - 22.05,24,16kHz) 1=(MPEG1 - 44.1,48,32kHz) */
66 int mode; /* 0=stereo, 1=jstereo, 2=dual, 3=mono */ 66 int mode; /* 0=stereo, 1=jstereo, 2=dual, 3=mono */
67 int bitrate; 67 int bitrate;
68 int padding; 68 int padding;
@@ -73,21 +73,20 @@ typedef struct {
73 73
74/* Side information */ 74/* Side information */
75typedef struct { 75typedef struct {
76 uint32 part2_3_length; 76 uint32_t part2_3_length;
77 int count1; /* number of 0-1-quadruples */ 77 int count1; /* number of 0-1-quadruples */
78 uint32 global_gain; 78 uint32_t global_gain;
79 uint32 table_select[4]; 79 uint32_t table_select[4];
80 uint32 region_0_1; 80 uint32_t region_0_1;
81 uint32 address1; 81 uint32_t address1;
82 uint32 address2; 82 uint32_t address2;
83 uint32 address3; 83 uint32_t address3;
84 long quantStep; 84 long quantStep;
85 long additStep; 85 long additStep;
86 long max_val; 86 long max_val;
87} side_info_t; 87} side_info_t;
88 88
89typedef struct { 89typedef struct {
90 enum e_byte_order byte_order;
91 side_info_t cod_info[2][2]; 90 side_info_t cod_info[2][2];
92 mpeg_t mpg; 91 mpeg_t mpg;
93 long frac_per_frame; 92 long frac_per_frame;
@@ -98,19 +97,18 @@ typedef struct {
98 int ResvSize; 97 int ResvSize;
99 int channels; 98 int channels;
100 int granules; 99 int granules;
101 int resample;
102 long samplerate; 100 long samplerate;
103} config_t; 101} config_t;
104 102
105typedef struct { 103typedef struct {
106 int bitpos; /* current bitpos for writing */ 104 int bitpos; /* current bitpos for writing */
107 uint32 bbuf[263]; 105 uint32_t bbuf[263];
108} BF_Data; 106} BF_Data;
109 107
110struct huffcodetab { 108struct huffcodetab {
111 int len; /* max. index */ 109 int len; /* max. index */
112 const uint8 *table; /* pointer to array[len][len] */ 110 const uint8_t *table; /* pointer to array[len][len] */
113 const uint8 *hlen; /* pointer to array[len][len] */ 111 const uint8_t *hlen; /* pointer to array[len][len] */
114}; 112};
115 113
116struct huffcodebig { 114struct huffcodebig {
@@ -127,102 +125,105 @@ struct huffcodebig {
127#define shft_n(x,n) ((x) >> n) 125#define shft_n(x,n) ((x) >> n)
128#define SQRT 724 /* sqrt(2) * 512 */ 126#define SQRT 724 /* sqrt(2) * 512 */
129 127
130short mfbuf [2*(1152+512)] IBSS_ATTR; /* 3328 Bytes */ 128static short mfbuf [2*(1152+512)] IBSS_ATTR; /* 3328 Bytes */
131int sb_data [2][2][18][SBLIMIT] IBSS_ATTR; /* 13824 Bytes */ 129static int sb_data [2][2][18][SBLIMIT] IBSS_ATTR; /* 13824 Bytes */
132int mdct_freq [SAMPL2] IBSS_ATTR; /* 9216 Bytes */ 130static int mdct_freq [SAMPL2] IBSS_ATTR; /* 9216 Bytes */
133short enc_data [SAMPL2] IBSS_ATTR; /* 4608 Bytes */ 131static short enc_data [SAMPL2] IBSS_ATTR; /* 4608 Bytes */
134uint32 scalefac [23] IBSS_ATTR; /* 92 Bytes */ 132static uint32_t scalefac [23] IBSS_ATTR; /* 92 Bytes */
135BF_Data CodedData IBSS_ATTR; /* 1056 Bytes */ 133static BF_Data CodedData IBSS_ATTR; /* 1056 Bytes */
136int ca [8] IBSS_ATTR; /* 32 Bytes */ 134static int ca [8] IBSS_ATTR; /* 32 Bytes */
137int cs [8] IBSS_ATTR; /* 32 Bytes */ 135static int cs [8] IBSS_ATTR; /* 32 Bytes */
138int cx [9] IBSS_ATTR; /* 36 Bytes */ 136static int cx [9] IBSS_ATTR; /* 36 Bytes */
139int win [18][4] IBSS_ATTR; /* 288 Bytes */ 137static int win [18][4] IBSS_ATTR; /* 288 Bytes */
140short enwindow [15*27+24] IBSS_ATTR; /* 862 Bytes */ 138static short enwindow [15*27+24] IBSS_ATTR; /* 862 Bytes */
141short int2idx [4096] IBSS_ATTR; /* 8192 Bytes */ 139static short int2idx [4096] IBSS_ATTR; /* 8192 Bytes */
142uint8 ht_count [2][2][16] IBSS_ATTR; /* 64 Bytes */ 140static uint8_t ht_count [2][2][16] IBSS_ATTR; /* 64 Bytes */
143uint32 tab01 [ 16] IBSS_ATTR; /* 64 Bytes */ 141static uint32_t tab01 [ 16] IBSS_ATTR; /* 64 Bytes */
144uint32 tab23 [ 9] IBSS_ATTR; /* 36 Bytes */ 142static uint32_t tab23 [ 9] IBSS_ATTR; /* 36 Bytes */
145uint32 tab56 [ 16] IBSS_ATTR; /* 64 Bytes */ 143static uint32_t tab56 [ 16] IBSS_ATTR; /* 64 Bytes */
146uint32 tab1315 [256] IBSS_ATTR; /* 1024 Bytes */ 144static uint32_t tab1315 [256] IBSS_ATTR; /* 1024 Bytes */
147uint32 tab1624 [256] IBSS_ATTR; /* 1024 Bytes */ 145static uint32_t tab1624 [256] IBSS_ATTR; /* 1024 Bytes */
148uint32 tab789 [ 36] IBSS_ATTR; /* 144 Bytes */ 146static uint32_t tab789 [ 36] IBSS_ATTR; /* 144 Bytes */
149uint32 tabABC [ 64] IBSS_ATTR; /* 256 Bytes */ 147static uint32_t tabABC [ 64] IBSS_ATTR; /* 256 Bytes */
150uint8 t1HB [ 4] IBSS_ATTR; 148static uint8_t t1HB [ 4] IBSS_ATTR;
151uint8 t2HB [ 9] IBSS_ATTR; 149static uint8_t t2HB [ 9] IBSS_ATTR;
152uint8 t3HB [ 9] IBSS_ATTR; 150static uint8_t t3HB [ 9] IBSS_ATTR;
153uint8 t5HB [ 16] IBSS_ATTR; 151static uint8_t t5HB [ 16] IBSS_ATTR;
154uint8 t6HB [ 16] IBSS_ATTR; 152static uint8_t t6HB [ 16] IBSS_ATTR;
155uint8 t7HB [ 36] IBSS_ATTR; 153static uint8_t t7HB [ 36] IBSS_ATTR;
156uint8 t8HB [ 36] IBSS_ATTR; 154static uint8_t t8HB [ 36] IBSS_ATTR;
157uint8 t9HB [ 36] IBSS_ATTR; 155static uint8_t t9HB [ 36] IBSS_ATTR;
158uint8 t10HB [ 64] IBSS_ATTR; 156static uint8_t t10HB [ 64] IBSS_ATTR;
159uint8 t11HB [ 64] IBSS_ATTR; 157static uint8_t t11HB [ 64] IBSS_ATTR;
160uint8 t12HB [ 64] IBSS_ATTR; 158static uint8_t t12HB [ 64] IBSS_ATTR;
161uint8 t13HB [256] IBSS_ATTR; 159static uint8_t t13HB [256] IBSS_ATTR;
162uint8 t15HB [256] IBSS_ATTR; 160static uint8_t t15HB [256] IBSS_ATTR;
163uint16 t16HB [256] IBSS_ATTR; 161static uint16_t t16HB [256] IBSS_ATTR;
164uint16 t24HB [256] IBSS_ATTR; 162static uint16_t t24HB [256] IBSS_ATTR;
165uint8 t1l [ 8] IBSS_ATTR; 163static uint8_t t1l [ 8] IBSS_ATTR;
166uint8 t2l [ 9] IBSS_ATTR; 164static uint8_t t2l [ 9] IBSS_ATTR;
167uint8 t3l [ 9] IBSS_ATTR; 165static uint8_t t3l [ 9] IBSS_ATTR;
168uint8 t5l [ 16] IBSS_ATTR; 166static uint8_t t5l [ 16] IBSS_ATTR;
169uint8 t6l [ 16] IBSS_ATTR; 167static uint8_t t6l [ 16] IBSS_ATTR;
170uint8 t7l [ 36] IBSS_ATTR; 168static uint8_t t7l [ 36] IBSS_ATTR;
171uint8 t8l [ 36] IBSS_ATTR; 169static uint8_t t8l [ 36] IBSS_ATTR;
172uint8 t9l [ 36] IBSS_ATTR; 170static uint8_t t9l [ 36] IBSS_ATTR;
173uint8 t10l [ 64] IBSS_ATTR; 171static uint8_t t10l [ 64] IBSS_ATTR;
174uint8 t11l [ 64] IBSS_ATTR; 172static uint8_t t11l [ 64] IBSS_ATTR;
175uint8 t12l [ 64] IBSS_ATTR; 173static uint8_t t12l [ 64] IBSS_ATTR;
176uint8 t13l [256] IBSS_ATTR; 174static uint8_t t13l [256] IBSS_ATTR;
177uint8 t15l [256] IBSS_ATTR; 175static uint8_t t15l [256] IBSS_ATTR;
178uint8 t16l [256] IBSS_ATTR; 176static uint8_t t16l [256] IBSS_ATTR;
179uint8 t24l [256] IBSS_ATTR; 177static uint8_t t24l [256] IBSS_ATTR;
180struct huffcodetab ht [HTN] IBSS_ATTR; 178static struct huffcodetab ht [HTN] IBSS_ATTR;
181 179
182static config_t cfg; 180static unsigned pcm_chunk_size IBSS_ATTR;
181static unsigned samp_per_frame IBSS_ATTR;
182
183static config_t cfg IBSS_ATTR;
183static struct codec_api *ci; 184static struct codec_api *ci;
184static int enc_channels; 185static char *res_buffer;
185 186
186static const uint8 ht_count_const[2][2][16] = 187static const uint8_t ht_count_const[2][2][16] =
187{ { { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1 }, /* table0 */ 188{ { { 1, 5, 4, 5, 6, 5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1 }, /* table0 */
188 { 1, 5, 5, 7, 5, 8, 7, 9, 5, 7, 7, 9, 7, 9, 9,10 } }, /* hleng0 */ 189 { 1, 5, 5, 7, 5, 8, 7, 9, 5, 7, 7, 9, 7, 9, 9,10 } }, /* hleng0 */
189 { {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, /* table1 */ 190 { {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }, /* table1 */
190 { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 } } }; /* hleng1 */ 191 { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 } } }; /* hleng1 */
191 192
192static const uint8 t1HB_const[4] = {1,1,1,0}; 193static const uint8_t t1HB_const[4] = {1,1,1,0};
193static const uint8 t2HB_const[9] = {1,2,1,3,1,1,3,2,0}; 194static const uint8_t t2HB_const[9] = {1,2,1,3,1,1,3,2,0};
194static const uint8 t3HB_const[9] = {3,2,1,1,1,1,3,2,0}; 195static const uint8_t t3HB_const[9] = {3,2,1,1,1,1,3,2,0};
195static const uint8 t5HB_const[16] = {1,2,6,5,3,1,4,4,7,5,7,1,6,1,1,0}; 196static const uint8_t t5HB_const[16] = {1,2,6,5,3,1,4,4,7,5,7,1,6,1,1,0};
196static const uint8 t6HB_const[16] = {7,3,5,1,6,2,3,2,5,4,4,1,3,3,2,0}; 197static const uint8_t t6HB_const[16] = {7,3,5,1,6,2,3,2,5,4,4,1,3,3,2,0};
197 198
198static const uint8 t7HB_const[36] = 199static const uint8_t t7HB_const[36] =
199{ 1, 2,10,19,16,10, 3, 3, 7,10, 5, 3,11, 4,13,17, 8, 4, 200{ 1, 2,10,19,16,10, 3, 3, 7,10, 5, 3,11, 4,13,17, 8, 4,
200 12,11,18,15,11, 2, 7, 6, 9,14, 3, 1, 6, 4, 5, 3, 2, 0 }; 201 12,11,18,15,11, 2, 7, 6, 9,14, 3, 1, 6, 4, 5, 3, 2, 0 };
201 202
202static const uint8 t8HB_const[36] = 203static const uint8_t t8HB_const[36] =
203{ 3, 4, 6,18,12, 5, 5, 1, 2,16, 9, 3, 7, 3, 5,14, 7, 3, 204{ 3, 4, 6,18,12, 5, 5, 1, 2,16, 9, 3, 7, 3, 5,14, 7, 3,
204 19,17,15,13,10, 4,13, 5, 8,11, 5, 1,12, 4, 4, 1, 1, 0 }; 205 19,17,15,13,10, 4,13, 5, 8,11, 5, 1,12, 4, 4, 1, 1, 0 };
205 206
206static const uint8 t9HB_const[36] = 207static const uint8_t t9HB_const[36] =
207{ 7, 5, 9,14,15, 7, 6, 4, 5, 5, 6, 7, 7, 6, 8, 8, 8, 5, 208{ 7, 5, 9,14,15, 7, 6, 4, 5, 5, 6, 7, 7, 6, 8, 8, 8, 5,
208 15, 6, 9,10, 5, 1,11, 7, 9, 6, 4, 1,14, 4, 6, 2, 6, 0 }; 209 15, 6, 9,10, 5, 1,11, 7, 9, 6, 4, 1,14, 4, 6, 2, 6, 0 };
209 210
210static const uint8 t10HB_const[64] = 211static const uint8_t t10HB_const[64] =
211{1,2,10,23,35,30,12,17,3,3,8,12,18,21,12,7,11,9,15,21,32, 212{1,2,10,23,35,30,12,17,3,3,8,12,18,21,12,7,11,9,15,21,32,
212 40,19,6,14,13,22,34,46,23,18,7,20,19,33,47,27,22,9,3,31,22, 213 40,19,6,14,13,22,34,46,23,18,7,20,19,33,47,27,22,9,3,31,22,
213 41,26,21,20,5,3,14,13,10,11,16,6,5,1,9,8,7,8,4,4,2,0 }; 214 41,26,21,20,5,3,14,13,10,11,16,6,5,1,9,8,7,8,4,4,2,0 };
214 215
215static const uint8 t11HB_const[64] = 216static const uint8_t t11HB_const[64] =
216{3,4,10,24,34,33,21,15,5,3,4,10,32,17,11,10,11,7,13,18,30, 217{3,4,10,24,34,33,21,15,5,3,4,10,32,17,11,10,11,7,13,18,30,
217 31,20,5,25,11,19,59,27,18,12,5,35,33,31,58,30,16,7,5,28,26, 218 31,20,5,25,11,19,59,27,18,12,5,35,33,31,58,30,16,7,5,28,26,
218 32,19,17,15,8,14,14,12,9,13,14,9,4,1,11,4,6,6,6,3,2,0 }; 219 32,19,17,15,8,14,14,12,9,13,14,9,4,1,11,4,6,6,6,3,2,0 };
219 220
220static const uint8 t12HB_const[64] = 221static const uint8_t t12HB_const[64] =
221{9,6,16,33,41,39,38,26,7,5,6,9,23,16,26,11,17,7,11,14,21, 222{9,6,16,33,41,39,38,26,7,5,6,9,23,16,26,11,17,7,11,14,21,
22230,10,7,17,10,15,12,18,28,14,5,32,13,22,19,18,16,9,5,40,17, 22330,10,7,17,10,15,12,18,28,14,5,32,13,22,19,18,16,9,5,40,17,
22331,29,17,13,4,2,27,12,11,15,10,7,4,1,27,12,8,12,6,3,1,0 }; 22431,29,17,13,4,2,27,12,11,15,10,7,4,1,27,12,8,12,6,3,1,0 };
224 225
225static const uint8 t13HB_const[256] = 226static const uint8_t t13HB_const[256] =
226{1,5,14,21,34,51,46,71,42,52,68,52,67,44,43,19,3,4,12,19,31,26,44,33,31,24,32, 227{1,5,14,21,34,51,46,71,42,52,68,52,67,44,43,19,3,4,12,19,31,26,44,33,31,24,32,
227 24,31,35,22,14,15,13,23,36,59,49,77,65,29,40,30,40,27,33,42,16,22,20,37,61,56, 228 24,31,35,22,14,15,13,23,36,59,49,77,65,29,40,30,40,27,33,42,16,22,20,37,61,56,
228 79,73,64,43,76,56,37,26,31,25,14,35,16,60,57,97,75,114,91,54,73,55,41,48,53, 229 79,73,64,43,76,56,37,26,31,25,14,35,16,60,57,97,75,114,91,54,73,55,41,48,53,
@@ -234,7 +235,7 @@ static const uint8 t13HB_const[256] =
234 45,21,34,64,56,50,49,45,31,19,12,15,10,7,6,3,48,23,20,39,36,35,53,21,16,23,13, 235 45,21,34,64,56,50,49,45,31,19,12,15,10,7,6,3,48,23,20,39,36,35,53,21,16,23,13,
235 10,6,1,4,2,16,15,17,27,25,20,29,11,17,12,16,8,1,1,0,1 }; 236 10,6,1,4,2,16,15,17,27,25,20,29,11,17,12,16,8,1,1,0,1 };
236 237
237static const uint8 t15HB_const[256] = 238static const uint8_t t15HB_const[256] =
238{7,12,18,53,47,76,124,108,89,123,108,119,107,81,122,63,13,5,16,27,46,36,61,51, 239{7,12,18,53,47,76,124,108,89,123,108,119,107,81,122,63,13,5,16,27,46,36,61,51,
239 42,70,52,83,65,41,59,36,19,17,15,24,41,34,59,48,40,64,50,78,62,80,56,33,29,28, 240 42,70,52,83,65,41,59,36,19,17,15,24,41,34,59,48,40,64,50,78,62,80,56,33,29,28,
240 25,43,39,63,55,93,76,59,93,72,54,75,50,29,52,22,42,40,67,57,95,79,72,57,89,69, 241 25,43,39,63,55,93,76,59,93,72,54,75,50,29,52,22,42,40,67,57,95,79,72,57,89,69,
@@ -246,7 +247,7 @@ static const uint8 t15HB_const[256] =
246 24,16,22,13,14,7,91,44,39,38,34,63,52,45,31,52,28,19,14,8,9,3,123,60,58,53,47, 247 24,16,22,13,14,7,91,44,39,38,34,63,52,45,31,52,28,19,14,8,9,3,123,60,58,53,47,
247 43,32,22,37,24,17,12,15,10,2,1,71,37,34,30,28,20,17,26,21,16,10,6,8,6,2,0}; 248 43,32,22,37,24,17,12,15,10,2,1,71,37,34,30,28,20,17,26,21,16,10,6,8,6,2,0};
248 249
249static const uint16 t16HB_const[256] = 250static const uint16_t t16HB_const[256] =
250{1,5,14,44,74,63,110,93,172,149,138,242,225,195,376,17,3,4,12,20,35,62,53,47, 251{1,5,14,44,74,63,110,93,172,149,138,242,225,195,376,17,3,4,12,20,35,62,53,47,
251 83,75,68,119,201,107,207,9,15,13,23,38,67,58,103,90,161,72,127,117,110,209, 252 83,75,68,119,201,107,207,9,15,13,23,38,67,58,103,90,161,72,127,117,110,209,
252 206,16,45,21,39,69,64,114,99,87,158,140,252,212,199,387,365,26,75,36,68,65, 253 206,16,45,21,39,69,64,114,99,87,158,140,252,212,199,387,365,26,75,36,68,65,
@@ -261,7 +262,7 @@ static const uint16 t16HB_const[256] =
261 358,711,709,866,1734,871,3458,870,434,0,12,10,7,11,10,17,11,9,13,12,10,7,5,3, 262 358,711,709,866,1734,871,3458,870,434,0,12,10,7,11,10,17,11,9,13,12,10,7,5,3,
262 1,3}; 263 1,3};
263 264
264static const uint16 t24HB_const[256] = 265static const uint16_t t24HB_const[256] =
265{15,13,46,80,146,262,248,434,426,669,653,649,621,517,1032,88,14,12,21,38,71, 266{15,13,46,80,146,262,248,434,426,669,653,649,621,517,1032,88,14,12,21,38,71,
266 130,122,216,209,198,327,345,319,297,279,42,47,22,41,74,68,128,120,221,207,194, 267 130,122,216,209,198,327,345,319,297,279,42,47,22,41,74,68,128,120,221,207,194,
267 182,340,315,295,541,18,81,39,75,70,134,125,116,220,204,190,178,325,311,293, 268 182,340,315,295,541,18,81,39,75,70,134,125,116,220,204,190,178,325,311,293,
@@ -276,7 +277,7 @@ static const uint16 t24HB_const[256] =
276 374,369,365,361,357,2,1033,280,278,274,267,264,259,382,378,372,367,363,360, 277 374,369,365,361,357,2,1033,280,278,274,267,264,259,382,378,372,367,363,360,
277 358,356,0,43,20,19,17,15,13,11,9,7,6,4,7,5,3,1,3}; 278 358,356,0,43,20,19,17,15,13,11,9,7,6,4,7,5,3,1,3};
278 279
279static const uint32 tab1315_const[256] = 280static const uint32_t tab1315_const[256] =
280{ 0x010003,0x050005,0x070006,0x080008,0x090008,0x0a0009,0x0a000a,0x0b000a, 281{ 0x010003,0x050005,0x070006,0x080008,0x090008,0x0a0009,0x0a000a,0x0b000a,
281 0x0a000a,0x0b000b,0x0c000b,0x0c000c,0x0d000c,0x0d000c,0x0e000d,0x0e000e, 282 0x0a000a,0x0b000b,0x0c000b,0x0c000c,0x0d000c,0x0d000c,0x0e000d,0x0e000e,
282 0x040005,0x060005,0x080007,0x090008,0x0a0009,0x0a0009,0x0b000a,0x0b000a, 283 0x040005,0x060005,0x080007,0x090008,0x0a0009,0x0a0009,0x0b000a,0x0b000a,
@@ -310,18 +311,18 @@ static const uint32 tab1315_const[256] =
310 0x0d000d,0x0e000d,0x0f000d,0x10000d,0x10000d,0x10000d,0x11000d,0x10000e, 311 0x0d000d,0x0e000d,0x0f000d,0x10000d,0x10000d,0x10000d,0x11000d,0x10000e,
311 0x11000e,0x11000e,0x12000e,0x12000e,0x15000f,0x14000f,0x15000f,0x12000f }; 312 0x11000e,0x11000e,0x12000e,0x12000e,0x15000f,0x14000f,0x15000f,0x12000f };
312 313
313static const uint32 tab01_const[16] = 314static const uint32_t tab01_const[16] =
314{ 0x10004,0x50005,0x50005,0x70006,0x50005,0x80006,0x70006,0x90007, 315{ 0x10004,0x50005,0x50005,0x70006,0x50005,0x80006,0x70006,0x90007,
315 0x50005,0x70006,0x70006,0x90007,0x70006,0x90007,0x90007,0xa0008 }; 316 0x50005,0x70006,0x70006,0x90007,0x70006,0x90007,0x90007,0xa0008 };
316 317
317static const uint32 tab23_const[ 9] = 318static const uint32_t tab23_const[ 9] =
318{ 0x10002,0x40003,0x70007,0x40004,0x50004,0x70007,0x60006,0x70007,0x80008 }; 319{ 0x10002,0x40003,0x70007,0x40004,0x50004,0x70007,0x60006,0x70007,0x80008 };
319 320
320static const uint32 tab56_const[16] = 321static const uint32_t tab56_const[16] =
321{ 0x10003,0x40004,0x70006,0x80008,0x40004,0x50004,0x80006,0x90007, 322{ 0x10003,0x40004,0x70006,0x80008,0x40004,0x50004,0x80006,0x90007,
322 0x70005,0x80006,0x90007,0xa0008,0x80007,0x80007,0x90008,0xa0009 }; 323 0x70005,0x80006,0x90007,0xa0008,0x80007,0x80007,0x90008,0xa0009 };
323 324
324static const uint32 tab789_const[36] = 325static const uint32_t tab789_const[36] =
325{0x00100803,0x00401004,0x00701c06,0x00902407,0x00902409,0x00a0280a,0x00401004, 326{0x00100803,0x00401004,0x00701c06,0x00902407,0x00902409,0x00a0280a,0x00401004,
326 0x00601005,0x00801806,0x00902807,0x00902808,0x00a0280a,0x00701c05,0x00701806, 327 0x00601005,0x00801806,0x00902807,0x00902808,0x00a0280a,0x00701c05,0x00701806,
327 0x00902007,0x00a02808,0x00a02809,0x00b02c0a,0x00802407,0x00902807,0x00a02808, 328 0x00902007,0x00a02808,0x00a02809,0x00b02c0a,0x00802407,0x00902807,0x00a02808,
@@ -329,7 +330,7 @@ static const uint32 tab789_const[36] =
329 0x00b0300a,0x00c0300b,0x00902809,0x00a02809,0x00b02c0a,0x00c02c0a,0x00c0340b, 330 0x00b0300a,0x00c0300b,0x00902809,0x00a02809,0x00b02c0a,0x00c02c0a,0x00c0340b,
330 0x00c0340b}; 331 0x00c0340b};
331 332
332static const uint32 tabABC_const[64] = 333static const uint32_t tabABC_const[64] =
333{0x00100804,0x00401004,0x00701806,0x00902008,0x00a02409,0x00a0280a,0x00a0240a, 334{0x00100804,0x00401004,0x00701806,0x00902008,0x00a02409,0x00a0280a,0x00a0240a,
334 0x00b0280a,0x00401004,0x00601405,0x00801806,0x00902007,0x00a02809,0x00b02809, 335 0x00b0280a,0x00401004,0x00601405,0x00801806,0x00902007,0x00a02809,0x00b02809,
335 0x00a0240a,0x00a0280a,0x00701806,0x00801c06,0x00902007,0x00a02408,0x00b02809, 336 0x00a0240a,0x00a0280a,0x00701806,0x00801c06,0x00902007,0x00a02408,0x00b02809,
@@ -341,7 +342,7 @@ static const uint32 tabABC_const[64] =
341 0x00a0240a,0x00a0240a,0x00b0280a,0x00c02c0b,0x00c0300b,0x00d0300b,0x00d0300b, 342 0x00a0240a,0x00a0240a,0x00b0280a,0x00c02c0b,0x00c0300b,0x00d0300b,0x00d0300b,
342 0x00d0300c}; 343 0x00d0300c};
343 344
344static const uint32 tab1624_const[256] = 345static const uint32_t tab1624_const[256] =
345{0x00010004,0x00050005,0x00070007,0x00090008,0x000a0009,0x000a000a,0x000b000a, 346{0x00010004,0x00050005,0x00070007,0x00090008,0x000a0009,0x000a000a,0x000b000a,
346 0x000b000b,0x000c000b,0x000c000c,0x000c000c,0x000d000c,0x000d000c,0x000d000c, 347 0x000b000b,0x000c000b,0x000c000c,0x000c000c,0x000d000c,0x000d000c,0x000d000c,
347 0x000e000d,0x000a000a,0x00040005,0x00060006,0x00080007,0x00090008,0x000a0009, 348 0x000e000d,0x000a000a,0x00040005,0x00060006,0x00080007,0x00090008,0x000a0009,
@@ -380,34 +381,34 @@ static const uint32 tab1624_const[256] =
380 0x000c0009,0x000c0009,0x000c0009,0x000d0009,0x000d0009,0x000d0009,0x000d000a, 381 0x000c0009,0x000c0009,0x000c0009,0x000d0009,0x000d0009,0x000d0009,0x000d000a,
381 0x000d000a,0x000d000a,0x000d000a,0x000a0006}; 382 0x000d000a,0x000d000a,0x000d000a,0x000a0006};
382 383
383static const uint8 t1l_const[8] = {1,3,2,3,1,4,3,5}; 384static const uint8_t t1l_const[8] = {1,3,2,3,1,4,3,5};
384static const uint8 t2l_const[9] = {1,3,6,3,3,5,5,5,6}; 385static const uint8_t t2l_const[9] = {1,3,6,3,3,5,5,5,6};
385static const uint8 t3l_const[9] = {2,2,6,3,2,5,5,5,6}; 386static const uint8_t t3l_const[9] = {2,2,6,3,2,5,5,5,6};
386static const uint8 t5l_const[16] = {1,3,6,7,3,3,6,7,6,6,7,8,7,6,7,8}; 387static const uint8_t t5l_const[16] = {1,3,6,7,3,3,6,7,6,6,7,8,7,6,7,8};
387static const uint8 t6l_const[16] = {3,3,5,7,3,2,4,5,4,4,5,6,6,5,6,7}; 388static const uint8_t t6l_const[16] = {3,3,5,7,3,2,4,5,4,4,5,6,6,5,6,7};
388 389
389static const uint8 t7l_const[36] = 390static const uint8_t t7l_const[36] =
390{1,3,6,8,8,9,3,4,6,7,7,8,6,5,7,8,8,9,7,7,8,9,9,9,7,7,8,9,9,10,8,8,9,10,10,10}; 391{1,3,6,8,8,9,3,4,6,7,7,8,6,5,7,8,8,9,7,7,8,9,9,9,7,7,8,9,9,10,8,8,9,10,10,10};
391 392
392static const uint8 t8l_const[36] = 393static const uint8_t t8l_const[36] =
393{2,3,6,8,8,9,3,2,4,8,8,8,6,4,6,8,8,9,8,8,8,9,9,10,8,7,8,9,10,10,9,8,9,9,11,11}; 394{2,3,6,8,8,9,3,2,4,8,8,8,6,4,6,8,8,9,8,8,8,9,9,10,8,7,8,9,10,10,9,8,9,9,11,11};
394 395
395static const uint8 t9l_const[36] = 396static const uint8_t t9l_const[36] =
396{3,3,5,6,8,9,3,3,4,5,6,8,4,4,5,6,7,8,6,5,6,7,7,8,7,6,7,7,8,9,8,7,8,8,9,9}; 397{3,3,5,6,8,9,3,3,4,5,6,8,4,4,5,6,7,8,6,5,6,7,7,8,7,6,7,7,8,9,8,7,8,8,9,9};
397 398
398static const uint8 t10l_const[64] = 399static const uint8_t t10l_const[64] =
399{1,3,6,8,9,9,9,10,3,4,6,7,8,9,8,8,6,6,7,8,9,10,9,9,7,7,8,9,10,10,9,10,8,8,9,10, 400{1,3,6,8,9,9,9,10,3,4,6,7,8,9,8,8,6,6,7,8,9,10,9,9,7,7,8,9,10,10,9,10,8,8,9,10,
400 10,10,10,10,9,9,10,10,11,11,10,11,8,8,9,10,10,10,11,11,9,8,9,10,10,11,11,11}; 401 10,10,10,10,9,9,10,10,11,11,10,11,8,8,9,10,10,10,11,11,9,8,9,10,10,11,11,11};
401 402
402static const uint8 t11l_const[64] = 403static const uint8_t t11l_const[64] =
403{2,3,5,7,8,9,8,9,3,3,4,6,8,8,7,8,5,5,6,7,8,9,8,8,7,6,7,9,8,10,8,9,8,8,8,9,9,10, 404{2,3,5,7,8,9,8,9,3,3,4,6,8,8,7,8,5,5,6,7,8,9,8,8,7,6,7,9,8,10,8,9,8,8,8,9,9,10,
404 9,10,8,8,9,10,10,11,10,11,8,7,7,8,9,10,10,10,8,7,8,9,10,10,10,10}; 405 9,10,8,8,9,10,10,11,10,11,8,7,7,8,9,10,10,10,8,7,8,9,10,10,10,10};
405 406
406static const uint8 t12l_const[64] = 407static const uint8_t t12l_const[64] =
407{4,3,5,7,8,9,9,9,3,3,4,5,7,7,8,8,5,4,5,6,7,8,7,8,6,5,6,6,7,8,8,8,7,6,7,7,8, 408{4,3,5,7,8,9,9,9,3,3,4,5,7,7,8,8,5,4,5,6,7,8,7,8,6,5,6,6,7,8,8,8,7,6,7,7,8,
408 8,8,9,8,7,8,8,8,9,8,9,8,7,7,8,8,9,9,10,9,8,8,9,9,9,9,10}; 409 8,8,9,8,7,8,8,8,9,8,9,8,7,7,8,8,9,9,10,9,8,8,9,9,9,9,10};
409 410
410static const uint8 t13l_const[256] = 411static const uint8_t t13l_const[256] =
411{1,4,6,7,8,9,9,10,9,10,11,11,12,12,13,13,3,4,6,7,8,8,9,9,9,9,10,10,11,12,12,12, 412{1,4,6,7,8,9,9,10,9,10,11,11,12,12,13,13,3,4,6,7,8,8,9,9,9,9,10,10,11,12,12,12,
412 6,6,7,8,9,9,10,10,9,10,10,11,11,12,13,13,7,7,8,9,9,10,10,10,10,11,11,11,11,12, 413 6,6,7,8,9,9,10,10,9,10,10,11,11,12,13,13,7,7,8,9,9,10,10,10,10,11,11,11,11,12,
413 13,13,8,7,9,9,10,10,11,11,10,11,11,12,12,13,13,14,9,8,9,10,10,10,11,11,11,11, 414 13,13,8,7,9,9,10,10,11,11,10,11,11,12,12,13,13,14,9,8,9,10,10,10,11,11,11,11,
@@ -419,7 +420,7 @@ static const uint8 t13l_const[256] =
419 16,16,13,12,12,13,13,13,15,14,14,17,15,15,15,17,16,16,12,12,13,14,14,14,15,14, 420 16,16,13,12,12,13,13,13,15,14,14,17,15,15,15,17,16,16,12,12,13,14,14,14,15,14,
420 15,15,16,16,19,18,19,16}; 421 15,15,16,16,19,18,19,16};
421 422
422static const uint8 t15l_const[256] = 423static const uint8_t t15l_const[256] =
423{3,4,5,7,7,8,9,9,9,10,10,11,11,11,12,13,4,3,5,6,7,7,8,8,8,9,9,10,10,10,11,11,5, 424{3,4,5,7,7,8,9,9,9,10,10,11,11,11,12,13,4,3,5,6,7,7,8,8,8,9,9,10,10,10,11,11,5,
424 5,5,6,7,7,8,8,8,9,9,10,10,11,11,11,6,6,6,7,7,8,8,9,9,9,10,10,10,11,11,11,7,6, 425 5,5,6,7,7,8,8,8,9,9,10,10,11,11,11,6,6,6,7,7,8,8,9,9,9,10,10,10,11,11,11,7,6,
425 7,7,8,8,9,9,9,9,10,10,10,11,11,11,8,7,7,8,8,8,9,9,9,9,10,10,11,11,11,12,9,7,8, 426 7,7,8,8,9,9,9,9,10,10,10,11,11,11,8,7,7,8,8,8,9,9,9,9,10,10,11,11,11,12,9,7,8,
@@ -430,7 +431,7 @@ static const uint8 t15l_const[256] =
430 11,11,11,11,12,12,12,12,12,13,13,12,11,11,11,11,11,11,11,12,12,12,12,13,13,12, 431 11,11,11,11,12,12,12,12,12,13,13,12,11,11,11,11,11,11,11,12,12,12,12,13,13,12,
431 13,12,11,11,11,11,11,11,12,12,12,12,12,13,13,13,13}; 432 13,12,11,11,11,11,11,11,12,12,12,12,12,13,13,13,13};
432 433
433static const uint8 t16l_const[256] = 434static const uint8_t t16l_const[256] =
434{1,4,6,8,9,9,10,10,11,11,11,12,12,12,13,9,3,4,6,7,8,9,9,9,10,10,10,11,12,11,12, 435{1,4,6,8,9,9,10,10,11,11,11,12,12,12,13,9,3,4,6,7,8,9,9,9,10,10,10,11,12,11,12,
435 8,6,6,7,8,9,9,10,10,11,10,11,11,11,12,12,9,8,7,8,9,9,10,10,10,11,11,12,12,12, 436 8,6,6,7,8,9,9,10,10,11,10,11,11,11,12,12,9,8,7,8,9,9,10,10,10,11,11,12,12,12,
436 13,13,10,9,8,9,9,10,10,11,11,11,12,12,12,13,13,13,9,9,8,9,9,10,11,11,12,11,12, 437 13,13,10,9,8,9,9,10,10,11,11,11,12,12,12,13,13,13,9,9,8,9,9,10,11,11,12,11,12,
@@ -442,7 +443,7 @@ static const uint8 t16l_const[256] =
442 17,15,11,13,13,11,12,14,14,13,14,14,15,16,15,17,15,14,11,9,8,8,9,9,10,10,10, 443 17,15,11,13,13,11,12,14,14,13,14,14,15,16,15,17,15,14,11,9,8,8,9,9,10,10,10,
443 11,11,11,11,11,11,11,8}; 444 11,11,11,11,11,11,11,8};
444 445
445static const uint8 t24l_const[256] = 446static const uint8_t t24l_const[256] =
446{4,4,6,7,8,9,9,10,10,11,11,11,11,11,12,9,4,4,5,6,7,8,8,9,9,9,10,10,10,10,10,8, 447{4,4,6,7,8,9,9,10,10,11,11,11,11,11,12,9,4,4,5,6,7,8,8,9,9,9,10,10,10,10,10,8,
447 6,5,6,7,7,8,8,9,9,9,9,10,10,10,11,7,7,6,7,7,8,8,8,9,9,9,9,10,10,10,10,7,8,7,7, 448 6,5,6,7,7,8,8,9,9,9,9,10,10,10,11,7,7,6,7,7,8,8,8,9,9,9,9,10,10,10,10,7,8,7,7,
448 8,8,8,8,9,9,9,10,10,10,10,11,7,9,7,8,8,8,8,9,9,9,9,10,10,10,10,10,7,9,8,8,8,8, 449 8,8,8,8,9,9,9,10,10,10,10,11,7,9,7,8,8,8,8,9,9,9,9,10,10,10,10,10,7,9,8,8,8,8,
@@ -491,8 +492,8 @@ static const struct huffcodebig ht_big[HTN] =
491 492
492static const struct 493static const struct
493{ 494{
494 uint32 region0_cnt; 495 uint32_t region0_cnt;
495 uint32 region1_cnt; 496 uint32_t region1_cnt;
496} subdv_table[23] = 497} subdv_table[23] =
497{ {0, 0}, /* 0 bands */ 498{ {0, 0}, /* 0 bands */
498 {0, 0}, /* 1 bands */ 499 {0, 0}, /* 1 bands */
@@ -519,7 +520,7 @@ static const struct
519 {6, 7}, /* 22 bands */ 520 {6, 7}, /* 22 bands */
520}; 521};
521 522
522static const uint32 sfBand[6][23] = 523static const uint32_t sfBand[6][23] =
523{ 524{
524/* Table B.2.b: 22.05 kHz */ 525/* Table B.2.b: 22.05 kHz */
525{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, 526{0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576},
@@ -747,9 +748,13 @@ static const int order[32] =
747{ 0, 1, 16, 17, 8, 9, 24, 25, 4, 5, 20, 21, 12, 13, 28, 29, 748{ 0, 1, 16, 17, 8, 9, 24, 25, 4, 5, 20, 21, 12, 13, 28, 29,
748 2, 3, 18, 19,10,11, 26, 27, 6, 7, 22, 23, 14, 15, 30, 31 }; 749 2, 3, 18, 19,10,11, 26, 27, 6, 7, 22, 23, 14, 15, 30, 31 };
749 750
750static const int bitr_index[2][15] = 751static const long sampr_index[2][3] =
751{ {0, 8,16,24,32,40,48,56, 64, 80, 96,112,128,144,160}, 752{ { 22050, 24000, 16000 }, /* MPEG 2 */
752 {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320} }; 753 { 44100, 48000, 32000 } }; /* MPEG 1 */
754
755static const long bitr_index[2][15] =
756{ {0, 8,16,24,32,40,48,56, 64, 80, 96,112,128,144,160}, /* MPEG 2 */
757 {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320} }; /* MPEG 1 */
753 758
754static const int num_bands[3][15] = 759static const int num_bands[3][15] =
755{ {0,10,10,10,10,12,14,16, 20, 22, 24, 26, 28, 30, 32}, 760{ {0,10,10,10,10,12,14,16, 20, 22, 24, 26, 28, 30, 32},
@@ -837,35 +842,55 @@ static const int win_const[18][4] = {
837 { 134, -146,-3352,-3072 } }; 842 { 134, -146,-3352,-3072 } };
838 843
839/* forward declarations */ 844/* forward declarations */
840int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table); 845static int HuffmanCode( short *ix, int *xr, uint32_t begin, uint32_t end, int table);
841int HuffmanCod1( short *ix, int *xr, uint32 begin, uint32 end, int table); 846static int HuffmanCod1( short *ix, int *xr, uint32_t begin, uint32_t end, int table);
842void putbits(uint32 val, uint32 nbit); 847static void putbits(uint32_t val, uint32_t nbit);
843int find_best_2( short *ix, uint32 start, uint32 end, const uint32 *table, 848static int find_best_2( short *ix, uint32_t start, uint32_t end, const uint32_t *table,
844 uint32 len, int *bits); 849 uint32_t len, int *bits);
845int find_best_3( short *ix, uint32 start, uint32 end, const uint32 *table, 850static int find_best_3( short *ix, uint32_t start, uint32_t end, const uint32_t *table,
846 uint32 len, int *bits); 851 uint32_t len, int *bits);
847int count_bit1 ( short *ix, uint32 start, uint32 end, int *bits ); 852static int count_bit1 ( short *ix, uint32_t start, uint32_t end, int *bits );
848int count_bigv ( short *ix, uint32 start, uint32 end, int table0, int table1, 853static int count_bigv ( short *ix, uint32_t start, uint32_t end, int table0, int table1,
849 int *bits); 854 int *bits);
850 855
851 856
852void encodeSideInfo( side_info_t si[2][2] ) 857static void encodeSideInfo( side_info_t si[2][2] )
853{ 858{
854 int gr, ch, header; 859 int gr, ch, header;
855 uint32 cc=0, sz=0; 860 uint32_t cc=0, sz=0;
856 861
857 header = 0xfff00000; 862 /*
858 header |= cfg.mpg.type << 19; /* mp3 type: 1 */ 863 * MPEG header layout:
859 header |= 1 << 17; /* mp3 layer: 1 */ 864 * AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
860 header |= 1 << 16; /* mp3 crc: 0 */ 865 * A (31-21) = frame sync
866 * B (20-19) = MPEG type
867 * C (18-17) = MPEG layer
868 * D (16) = protection bit
869 * E (15-12) = bitrate index
870 * F (11-10) = samplerate index
871 * G (9) = padding bit
872 * H (8) = private bit
873 * I (7-6) = channel mode
874 * J (5-4) = mode extension (jstereo only)
875 * K (3) = copyright bit
876 * L (2) = original
877 * M (1-0) = emphasis
878 */
879
880 header = (0xfff00000) | /* frame sync (AAAAAAAAA AAA)
881 mp3 type (upper): 1 (B) */
882 (0x01 << 17) | /* mp3 layer: 01 (CC) */
883 ( 0x1 << 16) | /* mp3 crc: 1 (D) */
884 ( 0x1 << 2); /* mp3 org: 1 (L) */
885 header |= cfg.mpg.type << 19;
861 header |= cfg.mpg.bitr_id << 12; 886 header |= cfg.mpg.bitr_id << 12;
862 header |= cfg.mpg.smpl_id << 10; 887 header |= cfg.mpg.smpl_id << 10;
863 header |= cfg.mpg.padding << 9; 888 header |= cfg.mpg.padding << 9;
864 header |= cfg.mpg.mode << 6; 889 header |= cfg.mpg.mode << 6;
865 header |= 1 << 2; /* mp3 original: 1 */ 890 /* no emphasis (bits 0-1) */
866 putbits( header, 32 ); 891 putbits( header, 32 );
867 892
868 if(cfg.mpg.type) 893 if(cfg.mpg.type == 1)
869 { /* MPEG1 */ 894 { /* MPEG1 */
870 if(cfg.channels == 2) { putlong( 0, 20); } 895 if(cfg.channels == 2) { putlong( 0, 20); }
871 else { putlong( 0, 18); } 896 else { putlong( 0, 18); }
@@ -910,7 +935,7 @@ void encodeSideInfo( side_info_t si[2][2] )
910 935
911/* Note the discussion of huffmancodebits() on pages 28 and 29 of the IS, 936/* Note the discussion of huffmancodebits() on pages 28 and 29 of the IS,
912 as well as the definitions of the side information on pages 26 and 27. */ 937 as well as the definitions of the side information on pages 26 and 27. */
913void Huffmancodebits( short *ix, int *xr, side_info_t *gi ) 938static void Huffmancodebits( short *ix, int *xr, side_info_t *gi )
914{ 939{
915 int region1 = gi->address1; 940 int region1 = gi->address1;
916 int region2 = gi->address2; 941 int region2 = gi->address2;
@@ -944,10 +969,10 @@ void Huffmancodebits( short *ix, int *xr, side_info_t *gi )
944 } 969 }
945} 970}
946 971
947int HuffmanCod1( short *ix, int *xr, uint32 begin, uint32 end, int tbl) 972int HuffmanCod1( short *ix, int *xr, uint32_t begin, uint32_t end, int tbl)
948{ 973{
949 uint32 cc=0, sz=0; 974 uint32_t cc=0, sz=0;
950 uint32 i, d, p; 975 uint32_t i, d, p;
951 int sumbit=0, s=0, l=0, v, w, x, y; 976 int sumbit=0, s=0, l=0, v, w, x, y;
952 #define sgnv (xr[i+0] < 0 ? 1 : 0) 977 #define sgnv (xr[i+0] < 0 ? 1 : 0)
953 #define sgnw (xr[i+1] < 0 ? 1 : 0) 978 #define sgnw (xr[i+1] < 0 ? 1 : 0)
@@ -995,10 +1020,10 @@ int HuffmanCod1( short *ix, int *xr, uint32 begin, uint32 end, int tbl)
995} 1020}
996 1021
997/* Implements the pseudocode of page 98 of the IS */ 1022/* Implements the pseudocode of page 98 of the IS */
998int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table) 1023int HuffmanCode( short *ix, int *xr, uint32_t begin, uint32_t end, int table)
999{ 1024{
1000 uint32 cc=0, sz=0, code; 1025 uint32_t cc=0, sz=0, code;
1001 uint32 i, xl=0, yl=0, idx; 1026 uint32_t i, xl=0, yl=0, idx;
1002 int x, y, bit, sumbit=0; 1027 int x, y, bit, sumbit=0;
1003 #define sign_x (xr[i+0] < 0 ? 1 : 0) 1028 #define sign_x (xr[i+0] < 0 ? 1 : 0)
1004 #define sign_y (xr[i+1] < 0 ? 1 : 0) 1029 #define sign_y (xr[i+1] < 0 ? 1 : 0)
@@ -1008,9 +1033,9 @@ int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table)
1008 1033
1009 if( table > 15 ) 1034 if( table > 15 )
1010 { /* ESC-table is used */ 1035 { /* ESC-table is used */
1011 uint32 linbits = ht_big[table-16].linbits; 1036 uint32_t linbits = ht_big[table-16].linbits;
1012 uint16 *hffcode = table < 24 ? t16HB : t24HB; 1037 uint16_t *hffcode = table < 24 ? t16HB : t24HB;
1013 uint8 *hlen = table < 24 ? t16l : t24l; 1038 uint8_t *hlen = table < 24 ? t16l : t24l;
1014 1039
1015 for(i=begin; i<end; i+=2) 1040 for(i=begin; i<end; i+=2)
1016 { 1041 {
@@ -1088,14 +1113,14 @@ int HuffmanCode( short *ix, int *xr, uint32 begin, uint32 end, int table)
1088 return sumbit; 1113 return sumbit;
1089} 1114}
1090 1115
1091void putbits(uint32 val, uint32 nbit) 1116void putbits(uint32_t val, uint32_t nbit)
1092{ 1117{
1093 int new_bitpos = CodedData.bitpos + nbit; 1118 int new_bitpos = CodedData.bitpos + nbit;
1094 int ptrpos = CodedData.bitpos >> 5; 1119 int ptrpos = CodedData.bitpos >> 5;
1095 1120
1096 val = val & (0xffffffff >> (32 - nbit)); 1121 val = val & (0xffffffff >> (32 - nbit));
1097 1122
1098 /* data fit in one uint32 */ 1123 /* data fit in one uint32_t */
1099 if(((new_bitpos - 1) >> 5) == ptrpos) 1124 if(((new_bitpos - 1) >> 5) == ptrpos)
1100 CodedData.bbuf[ptrpos] |= val << ((32 - new_bitpos) & 31); 1125 CodedData.bbuf[ptrpos] |= val << ((32 - new_bitpos) & 31);
1101 else 1126 else
@@ -1114,9 +1139,9 @@ void putbits(uint32 val, uint32 nbit)
1114/* of the Huffman tables as defined in the IS (Table B.7), and will not */ 1139/* of the Huffman tables as defined in the IS (Table B.7), and will not */
1115/* work with any arbitrary tables. */ 1140/* work with any arbitrary tables. */
1116/***************************************************************************/ 1141/***************************************************************************/
1117int choose_table( short *ix, uint32 begin, uint32 end, int *bits ) 1142int choose_table( short *ix, uint32_t begin, uint32_t end, int *bits )
1118{ 1143{
1119 uint32 i; 1144 uint32_t i;
1120 int max, table0, table1; 1145 int max, table0, table1;
1121 1146
1122 for(i=begin,max=0; i<end; i++) 1147 for(i=begin,max=0; i<end; i++)
@@ -1158,10 +1183,10 @@ int choose_table( short *ix, uint32 begin, uint32 end, int *bits )
1158 } 1183 }
1159} 1184}
1160 1185
1161int find_best_2(short *ix, uint32 start, uint32 end, const uint32 *table, 1186int find_best_2(short *ix, uint32_t start, uint32_t end, const uint32_t *table,
1162 uint32 len, int *bits) 1187 uint32_t len, int *bits)
1163{ 1188{
1164 uint32 i, sum = 0; 1189 uint32_t i, sum = 0;
1165 1190
1166 for(i=start; i<end; i+=2) 1191 for(i=start; i<end; i+=2)
1167 sum += table[ix[i] * len + ix[i+1]]; 1192 sum += table[ix[i] * len + ix[i+1]];
@@ -1178,10 +1203,10 @@ int find_best_2(short *ix, uint32 start, uint32 end, const uint32 *table,
1178 } 1203 }
1179} 1204}
1180 1205
1181int find_best_3(short *ix, uint32 start, uint32 end, const uint32 *table, 1206int find_best_3(short *ix, uint32_t start, uint32_t end, const uint32_t *table,
1182 uint32 len, int *bits) 1207 uint32_t len, int *bits)
1183{ 1208{
1184 uint32 i, j, sum = 0; 1209 uint32_t i, j, sum = 0;
1185 int sum1 = 0; 1210 int sum1 = 0;
1186 int sum2 = 0; 1211 int sum2 = 0;
1187 int sum3 = 0; 1212 int sum3 = 0;
@@ -1211,9 +1236,9 @@ int find_best_3(short *ix, uint32 start, uint32 end, const uint32 *table,
1211/*************************************************************************/ 1236/*************************************************************************/
1212/* Function: Count the number of bits necessary to code the subregion. */ 1237/* Function: Count the number of bits necessary to code the subregion. */
1213/*************************************************************************/ 1238/*************************************************************************/
1214int count_bit1(short *ix, uint32 start, uint32 end, int *bits ) 1239int count_bit1(short *ix, uint32_t start, uint32_t end, int *bits )
1215{ 1240{
1216 uint32 i, sum = 0; 1241 uint32_t i, sum = 0;
1217 1242
1218 for(i=start; i<end; i+=2) 1243 for(i=start; i<end; i+=2)
1219 sum += t1l[4 + ix[i] * 2 + ix[i+1]]; 1244 sum += t1l[4 + ix[i] * 2 + ix[i+1]];
@@ -1223,10 +1248,10 @@ int count_bit1(short *ix, uint32 start, uint32 end, int *bits )
1223 return 1; /* this is table1 */ 1248 return 1; /* this is table1 */
1224} 1249}
1225 1250
1226int count_bigv(short *ix, uint32 start, uint32 end, int table0, 1251int count_bigv(short *ix, uint32_t start, uint32_t end, int table0,
1227 int table1, int *bits ) 1252 int table1, int *bits )
1228{ 1253{
1229 uint32 i, sum0, sum1, sum=0, bigv=0, x, y; 1254 uint32_t i, sum0, sum1, sum=0, bigv=0, x, y;
1230 1255
1231 /* ESC-table is used */ 1256 /* ESC-table is used */
1232 for(i=start; i<end; i+=2) 1257 for(i=start; i<end; i+=2)
@@ -1264,7 +1289,7 @@ int calc_runlen( short *ix, side_info_t *si )
1264 int p, i, sum = 0; 1289 int p, i, sum = 0;
1265 1290
1266 for(i=SAMPL2; i-=2; ) 1291 for(i=SAMPL2; i-=2; )
1267 if(*(uint32*)&ix[i-2]) /* !!!! short *ix; !!!!! */ 1292 if(*(uint32_t*)&ix[i-2]) /* !!!! short *ix; !!!!! */
1268 break; 1293 break;
1269 1294
1270 si->count1 = 0; 1295 si->count1 = 0;
@@ -1899,276 +1924,275 @@ void mdct_long(int *out, int *in)
1899 out[16] = ct - st; 1924 out[16] = ct - st;
1900} 1925}
1901 1926
1902static int find_bitrate_index(int type, int bitrate) 1927static int find_bitrate_index(int type, int bitrate, bool stereo)
1903{ 1928{
1904 int i; 1929 if (type == 1 && !stereo && bitrate > 160)
1930 bitrate = 160;
1905 1931
1906 for(i=0;i<14;i++) 1932 return ci->round_value_to_list32(bitrate,
1907 if(bitrate == bitr_index[type][i]) 1933 &bitr_index[type][1], 14, true) + 1;
1908 break;
1909
1910 return i;
1911} 1934}
1912 1935
1913static int find_samplerate_index(long freq, int *mp3_type) 1936static int find_samplerate_index(long freq, int *mp3_type)
1914{ /* MPEG 2 */ /* MPEG 1 */ 1937{
1915 static long mpeg[2][3] = { {22050, 24000, 16000}, {44100, 48000, 32000} }; 1938 int mpeg = freq >= (32000+24000)/2 ? 1 : 0;
1916 int mpg, rate; 1939 int i = ci->round_value_to_list32(freq, sampr_index[mpeg], 3, true);
1917 1940 *mp3_type = mpeg;
1918 /* set default values: MPEG1 at 44100/s */ 1941 return i;
1919 *mp3_type = 1;
1920
1921 for(mpg=0; mpg<2; mpg++)
1922 for(rate=0; rate<3; rate++)
1923 if(freq == mpeg[mpg][rate])
1924 { *mp3_type = mpg; return rate; }
1925
1926 return 0;
1927} 1942}
1928 1943
1929void init_mp3_encoder_engine(bool stereo, int quality, int sample_rate) 1944bool init_mp3_encoder_engine(int sample_rate,
1945 int num_channels,
1946 struct encoder_config *enc_cfg)
1930{ 1947{
1931 /* keep in sync with rec_quality_info_afmt in id3.h/.c */ 1948 const bool stereo = num_channels > 1;
1932 static int bitr_s[9] = { 64, 96, 128, 160, 192, 224, 320, 64, 64 }; 1949 uint32_t avg_byte_per_frame;
1933 static int bitr_m[9] = { 64, 96, 128, 160, 160, 160, 160, 64, 64 }; 1950
1934 uint32 avg_byte_per_frame; 1951 cfg.channels = stereo ? 2 : 1;
1935 1952 cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */
1936 if(quality == 0 && stereo && sample_rate >= 32000) 1953 cfg.mpg.smpl_id = find_samplerate_index(sample_rate, &cfg.mpg.type);
1937 { /* use MPEG2 format */ 1954 cfg.samplerate = sampr_index[cfg.mpg.type][cfg.mpg.smpl_id];
1938 sample_rate >>= 1; 1955 cfg.mpg.bitr_id = find_bitrate_index(cfg.mpg.type,
1939 cfg.resample = 1; 1956 enc_cfg->mp3_enc.bitrate,
1940 cfg.granules = 1; 1957 stereo);
1941 } 1958 cfg.mpg.bitrate = bitr_index[cfg.mpg.type][cfg.mpg.bitr_id];
1942 else 1959 cfg.mpg.num_bands = num_bands[stereo ? cfg.mpg.type : 2][cfg.mpg.bitr_id];
1943 { /* use MPEG1 format */ 1960
1944 cfg.resample = 0; 1961 if (cfg.mpg.type == 1)
1945 cfg.granules = 2; 1962 {
1946 } 1963 cfg.granules = 2;
1964 pcm_chunk_size = PCM_CHUNK_SIZE1;
1965 samp_per_frame = SAMP_PER_FRAME1;
1966 }
1967 else
1968 {
1969 cfg.granules = 1;
1970 pcm_chunk_size = PCM_CHUNK_SIZE2;
1971 samp_per_frame = SAMP_PER_FRAME2;
1972 }
1947 1973
1948 cfg.byte_order = order_bigEndian; 1974 memcpy(scalefac, sfBand[cfg.mpg.smpl_id + 3*cfg.mpg.type], sizeof(scalefac));
1949 cfg.samplerate = sample_rate; 1975 memset(mfbuf , 0 , sizeof(mfbuf ));
1950 cfg.channels = stereo ? 2 : 1; 1976 memset(mdct_freq , 0 , sizeof(mdct_freq ));
1951 cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */ 1977 memset(enc_data , 0 , sizeof(enc_data ));
1952 cfg.mpg.bitrate = stereo ? bitr_s[quality] : bitr_m[quality]; 1978 memset(sb_data , 0 , sizeof(sb_data ));
1953 cfg.mpg.smpl_id = find_samplerate_index(cfg.samplerate, &cfg.mpg.type); 1979 memset(&CodedData, 0 , sizeof(CodedData ));
1954 cfg.mpg.bitr_id = find_bitrate_index(cfg.mpg.type, cfg.mpg.bitrate); 1980 memcpy(ca , ca_const , sizeof(ca ));
1955 cfg.mpg.num_bands = num_bands[stereo ? cfg.mpg.type : 2][cfg.mpg.bitr_id]; 1981 memcpy(cs , cs_const , sizeof(cs ));
1956 1982 memcpy(cx , cx_const , sizeof(cx ));
1957 memcpy(scalefac, sfBand[cfg.mpg.smpl_id + 3*cfg.mpg.type], sizeof(scalefac)); 1983 memcpy(win , win_const , sizeof(win ));
1958 memset(mfbuf , 0 , sizeof(mfbuf )); 1984 memcpy(enwindow , enwindow_const , sizeof(enwindow ));
1959 memset(mdct_freq , 0 , sizeof(mdct_freq )); 1985 memcpy(int2idx , int2idx_const , sizeof(int2idx ));
1960 memset(enc_data , 0 , sizeof(enc_data )); 1986 memcpy(ht_count , ht_count_const , sizeof(ht_count ));
1961 memset(sb_data , 0 , sizeof(sb_data )); 1987 memcpy( tab01 , tab01_const , sizeof(tab01 ));
1962 memset(&CodedData, 0 , sizeof(CodedData )); 1988 memcpy( tab23 , tab23_const , sizeof(tab23 ));
1963 memcpy(ca , ca_const , sizeof(ca )); 1989 memcpy( tab56 , tab56_const , sizeof(tab56 ));
1964 memcpy(cs , cs_const , sizeof(cs )); 1990 memcpy( tab1315 , tab1315_const , sizeof(tab1315 ));
1965 memcpy(cx , cx_const , sizeof(cx )); 1991 memcpy( tab1624 , tab1624_const , sizeof(tab1624 ));
1966 memcpy(win , win_const , sizeof(win )); 1992 memcpy( tab789 , tab789_const , sizeof(tab789 ));
1967 memcpy(enwindow , enwindow_const , sizeof(enwindow )); 1993 memcpy( tabABC , tabABC_const , sizeof(tabABC ));
1968 memcpy(int2idx , int2idx_const , sizeof(int2idx )); 1994 memcpy( t1HB , t1HB_const , sizeof(t1HB ));
1969 memcpy(ht_count , ht_count_const , sizeof(ht_count )); 1995 memcpy( t2HB , t2HB_const , sizeof(t2HB ));
1970 memcpy( tab01 , tab01_const , sizeof(tab01 )); 1996 memcpy( t3HB , t3HB_const , sizeof(t3HB ));
1971 memcpy( tab23 , tab23_const , sizeof(tab23 )); 1997 memcpy( t5HB , t5HB_const , sizeof(t5HB ));
1972 memcpy( tab56 , tab56_const , sizeof(tab56 )); 1998 memcpy( t6HB , t6HB_const , sizeof(t6HB ));
1973 memcpy( tab1315 , tab1315_const , sizeof(tab1315 )); 1999 memcpy( t7HB , t7HB_const , sizeof(t7HB ));
1974 memcpy( tab1624 , tab1624_const , sizeof(tab1624 )); 2000 memcpy( t8HB , t8HB_const , sizeof(t8HB ));
1975 memcpy( tab789 , tab789_const , sizeof(tab789 )); 2001 memcpy( t9HB , t9HB_const , sizeof(t9HB ));
1976 memcpy( tabABC , tabABC_const , sizeof(tabABC )); 2002 memcpy(t10HB , t10HB_const , sizeof(t10HB ));
1977 memcpy( t1HB , t1HB_const , sizeof(t1HB )); 2003 memcpy(t11HB , t11HB_const , sizeof(t11HB ));
1978 memcpy( t2HB , t2HB_const , sizeof(t2HB )); 2004 memcpy(t12HB , t12HB_const , sizeof(t12HB ));
1979 memcpy( t3HB , t3HB_const , sizeof(t3HB )); 2005 memcpy(t13HB , t13HB_const , sizeof(t13HB ));
1980 memcpy( t5HB , t5HB_const , sizeof(t5HB )); 2006 memcpy(t15HB , t15HB_const , sizeof(t15HB ));
1981 memcpy( t6HB , t6HB_const , sizeof(t6HB )); 2007 memcpy(t16HB , t16HB_const , sizeof(t16HB ));
1982 memcpy( t7HB , t7HB_const , sizeof(t7HB )); 2008 memcpy(t24HB , t24HB_const , sizeof(t24HB ));
1983 memcpy( t8HB , t8HB_const , sizeof(t8HB )); 2009 memcpy( t1l , t1l_const , sizeof(t1l ));
1984 memcpy( t9HB , t9HB_const , sizeof(t9HB )); 2010 memcpy( t2l , t2l_const , sizeof(t2l ));
1985 memcpy(t10HB , t10HB_const , sizeof(t10HB )); 2011 memcpy( t3l , t3l_const , sizeof(t3l ));
1986 memcpy(t11HB , t11HB_const , sizeof(t11HB )); 2012 memcpy( t5l , t5l_const , sizeof(t5l ));
1987 memcpy(t12HB , t12HB_const , sizeof(t12HB )); 2013 memcpy( t6l , t6l_const , sizeof(t6l ));
1988 memcpy(t13HB , t13HB_const , sizeof(t13HB )); 2014 memcpy( t7l , t7l_const , sizeof(t7l ));
1989 memcpy(t15HB , t15HB_const , sizeof(t15HB )); 2015 memcpy( t8l , t8l_const , sizeof(t8l ));
1990 memcpy(t16HB , t16HB_const , sizeof(t16HB )); 2016 memcpy( t9l , t9l_const , sizeof(t9l ));
1991 memcpy(t24HB , t24HB_const , sizeof(t24HB )); 2017 memcpy(t10l , t10l_const , sizeof(t10l ));
1992 memcpy( t1l , t1l_const , sizeof(t1l )); 2018 memcpy(t11l , t11l_const , sizeof(t11l ));
1993 memcpy( t2l , t2l_const , sizeof(t2l )); 2019 memcpy(t12l , t12l_const , sizeof(t12l ));
1994 memcpy( t3l , t3l_const , sizeof(t3l )); 2020 memcpy(t13l , t13l_const , sizeof(t13l ));
1995 memcpy( t5l , t5l_const , sizeof(t5l )); 2021 memcpy(t15l , t15l_const , sizeof(t15l ));
1996 memcpy( t6l , t6l_const , sizeof(t6l )); 2022 memcpy(t16l , t16l_const , sizeof(t16l ));
1997 memcpy( t7l , t7l_const , sizeof(t7l )); 2023 memcpy(t24l , t24l_const , sizeof(t24l ));
1998 memcpy( t8l , t8l_const , sizeof(t8l )); 2024 memcpy(ht , ht_const , sizeof(ht ));
1999 memcpy( t9l , t9l_const , sizeof(t9l )); 2025
2000 memcpy(t10l , t10l_const , sizeof(t10l )); 2026 ht[ 0].table = NULL; ht[ 0].hlen = NULL; /* Apparently not used */
2001 memcpy(t11l , t11l_const , sizeof(t11l )); 2027 ht[ 1].table = t1HB; ht[ 1].hlen = t1l;
2002 memcpy(t12l , t12l_const , sizeof(t12l )); 2028 ht[ 2].table = t2HB; ht[ 2].hlen = t2l;
2003 memcpy(t13l , t13l_const , sizeof(t13l )); 2029 ht[ 3].table = t3HB; ht[ 3].hlen = t3l;
2004 memcpy(t15l , t15l_const , sizeof(t15l )); 2030 ht[ 4].table = NULL; ht[ 4].hlen = NULL; /* Apparently not used */
2005 memcpy(t16l , t16l_const , sizeof(t16l )); 2031 ht[ 5].table = t5HB; ht[ 5].hlen = t5l;
2006 memcpy(t24l , t24l_const , sizeof(t24l )); 2032 ht[ 6].table = t6HB; ht[ 6].hlen = t6l;
2007 memcpy(ht , ht_const , sizeof(ht )); 2033 ht[ 7].table = t7HB; ht[ 7].hlen = t7l;
2008 2034 ht[ 8].table = t8HB; ht[ 8].hlen = t8l;
2009 ht[ 0].table = NULL; ht[ 0].hlen = NULL; /* Apparently not used */ 2035 ht[ 9].table = t9HB; ht[ 9].hlen = t9l;
2010 ht[ 1].table = t1HB; ht[ 1].hlen = t1l; 2036 ht[10].table = t10HB; ht[10].hlen = t10l;
2011 ht[ 2].table = t2HB; ht[ 2].hlen = t2l; 2037 ht[11].table = t11HB; ht[11].hlen = t11l;
2012 ht[ 3].table = t3HB; ht[ 3].hlen = t3l; 2038 ht[12].table = t12HB; ht[12].hlen = t12l;
2013 ht[ 4].table = NULL; ht[ 4].hlen = NULL; /* Apparently not used */ 2039 ht[13].table = t13HB; ht[13].hlen = t13l;
2014 ht[ 5].table = t5HB; ht[ 5].hlen = t5l; 2040 ht[14].table = NULL; ht[14].hlen = NULL; /* Apparently not used */
2015 ht[ 6].table = t6HB; ht[ 6].hlen = t6l; 2041 ht[15].table = t15HB; ht[15].hlen = t15l;
2016 ht[ 7].table = t7HB; ht[ 7].hlen = t7l; 2042
2017 ht[ 8].table = t8HB; ht[ 8].hlen = t8l; 2043 /* Figure average number of 'bytes' per frame */
2018 ht[ 9].table = t9HB; ht[ 9].hlen = t9l; 2044 avg_byte_per_frame = SAMPL2 * 16000 * cfg.mpg.bitrate / (2 - cfg.mpg.type);
2019 ht[10].table = t10HB; ht[10].hlen = t10l; 2045 avg_byte_per_frame = avg_byte_per_frame / cfg.samplerate;
2020 ht[11].table = t11HB; ht[11].hlen = t11l; 2046 cfg.byte_per_frame = avg_byte_per_frame / 64;
2021 ht[12].table = t12HB; ht[12].hlen = t12l; 2047 cfg.frac_per_frame = avg_byte_per_frame & 63;
2022 ht[13].table = t13HB; ht[13].hlen = t13l; 2048 cfg.slot_lag = 0;
2023 ht[14].table = NULL; ht[14].hlen = NULL; /* Apparently not used */ 2049 cfg.sideinfo_len = 32 + (cfg.mpg.type ? (cfg.channels == 1 ? 136 : 256)
2024 ht[15].table = t15HB; ht[15].hlen = t15l; 2050 : (cfg.channels == 1 ? 72 : 136));
2025 2051
2026 /* Figure average number of 'bytes' per frame */ 2052 return true;
2027 avg_byte_per_frame = SAMPL2 * 16000 * cfg.mpg.bitrate / (2 - cfg.mpg.type);
2028 avg_byte_per_frame = avg_byte_per_frame / cfg.samplerate;
2029 cfg.byte_per_frame = avg_byte_per_frame / 64;
2030 cfg.frac_per_frame = avg_byte_per_frame & 63;
2031 cfg.slot_lag = 0;
2032 cfg.sideinfo_len = 32 + (cfg.mpg.type ? (cfg.channels == 1 ? 136 : 256)
2033 : (cfg.channels == 1 ? 72 : 136));
2034} 2053}
2035 2054
2036 2055static void to_mono_mm(void) ICODE_ATTR;
2037enum codec_status codec_start(struct codec_api* api) 2056static void to_mono_mm(void)
2038{ 2057{
2039 int i, ii, gr, k, ch, shift, gr_cnt; 2058 /* |llllllllllllllll|rrrrrrrrrrrrrrrr| =>
2040 int max, min; 2059 * |mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
2041 long *buffer; 2060 */
2042 int chunk_size, num_chunks; 2061 uint32_t *samp = (uint32_t *)&mfbuf[2*512];
2043 int enc_buffer_size; 2062 uint32_t *samp_end = samp + samp_per_frame;
2044 int enc_quality;
2045 uint32 *mp3_chunk_ptr;
2046 bool cpu_boosted = true; /* start boosted */
2047 2063
2048 /* Generic codec initialisation */ 2064 inline void to_mono(uint32_t **samp)
2049 ci = api; 2065 {
2050 2066 int32_t lr = **samp;
2051#ifdef USE_IRAM 2067 int32_t m = ((int16_t)lr + (lr >> 16)) >> 1;
2052 memcpy(iramstart, iramcopy, iramend - iramstart); 2068 *(*samp)++ = (m << 16) | (uint16_t)m;
2053 memset(iedata, 0, iend - iedata); 2069 } /* to_mono */
2054#endif
2055
2056 if(ci->enc_get_inputs == NULL ||
2057 ci->enc_set_parameters == NULL ||
2058 ci->enc_alloc_chunk == NULL ||
2059 ci->enc_free_chunk == NULL ||
2060 ci->enc_wavbuf_near_empty == NULL ||
2061 ci->enc_get_wav_data == NULL ||
2062 ci->enc_set_header_callback == NULL )
2063 return CODEC_ERROR;
2064 2070
2065 ci->cpu_boost(true); 2071 do
2072 {
2073 to_mono(&samp);
2074 to_mono(&samp);
2075 to_mono(&samp);
2076 to_mono(&samp);
2077 to_mono(&samp);
2078 to_mono(&samp);
2079 to_mono(&samp);
2080 to_mono(&samp);
2081 }
2082 while (samp < samp_end);
2083} /* to_mono_mm */
2084
2085#ifdef ROCKBOX_LITTLE_ENDIAN
2086/* Swaps a frame to big endian */
2087static inline void byte_swap_frame32(uint32_t *dst, uint32_t *src,
2088 size_t size) ICODE_ATTR;
2089static inline void byte_swap_frame32(uint32_t *dst, uint32_t *src,
2090 size_t size)
2091{
2092 uint32_t *src_end = SKIPBYTES(src, size);
2066 2093
2067 *ci->enc_set_header_callback = NULL; 2094 do
2068 ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality); 2095 {
2096 *dst++ = swap32(*src++);
2097 *dst++ = swap32(*src++);
2098 *dst++ = swap32(*src++);
2099 *dst++ = swap32(*src++);
2100 *dst++ = swap32(*src++);
2101 *dst++ = swap32(*src++);
2102 *dst++ = swap32(*src++);
2103 *dst++ = swap32(*src++);
2104 }
2105 while(src < src_end);
2106} /* byte_swap_frame32 */
2107#endif /* ROCKBOX_LITTLE_ENDIAN */
2069 2108
2070 init_mp3_encoder_engine(enc_channels == 2, enc_quality, 44100); 2109static void encode_frame(char *buffer, struct enc_chunk_hdr *chunk) ICODE_ATTR;
2110static void encode_frame(char *buffer, struct enc_chunk_hdr *chunk)
2111{
2112 int gr, gr_cnt;
2113 int max, min;
2071 2114
2072 /* must be 4byte aligned */ 2115 /* encode one mp3 frame in this loop */
2073 chunk_size = (sizeof(long) + cfg.byte_per_frame + 1 + 3) & ~3; 2116 CodedData.bitpos = 0;
2074 num_chunks = enc_buffer_size / chunk_size; 2117 memset(CodedData.bbuf, 0, sizeof(CodedData.bbuf));
2075 2118
2076 /* inform the main program about the buffer dimensions */ 2119 if((cfg.slot_lag += cfg.frac_per_frame) >= 64)
2077 ci->enc_set_parameters(chunk_size, num_chunks, SAMP_PER_FRAME, 2120 { /* Padding for this frame */
2078 NULL, 0, AFMT_MPA_L3); 2121 cfg.slot_lag -= 64;
2122 cfg.mpg.padding = 1;
2123 }
2124 else
2125 cfg.mpg.padding = 0;
2079 2126
2080#ifdef CPU_COLDFIRE 2127 cfg.mean_bits = (8 * cfg.byte_per_frame + 8 * cfg.mpg.padding
2081 asm volatile ("move.l #0, %macsr"); /* integer mode */ 2128 - cfg.sideinfo_len) / cfg.granules / cfg.channels;
2082#endif
2083 2129
2084 /* main application waits for this flag during encoder loading */ 2130 /* shift out old samples */
2085 ci->enc_codec_loaded = true; 2131 memcpy(mfbuf, mfbuf + 2*cfg.granules*576, 4*512);
2086 2132
2087 /* main encoding loop */ 2133 if (chunk->flags & CHUNKF_START_FILE)
2088 while(!ci->stop_codec)
2089 { 2134 {
2090 while((buffer = (long*)ci->enc_get_wav_data(SAMP_PER_FRAME*4)) != NULL) 2135 /* prefix silent samples for encoder delay */
2091 { 2136 memset(mfbuf + 2*512, 0, ENC_DELAY_SIZE);
2092 if(ci->stop_codec) 2137 /* read new samples to iram for further processing */
2093 break; 2138 memcpy(mfbuf + 2*512 + ENC_DELAY_SIZE/2,
2094 2139 buffer, pcm_chunk_size - ENC_DELAY_SIZE);
2095 if(ci->enc_wavbuf_near_empty() == 0) 2140 chunk->num_pcm = samp_per_frame - ENC_DELAY_SAMP;
2096 { 2141 }
2097 if(!cpu_boosted) 2142 else
2098 { 2143 {
2099 ci->cpu_boost(true); 2144 /* read new samples to iram for further processing */
2100 cpu_boosted = true; 2145 memcpy(mfbuf + 2*512, buffer, pcm_chunk_size);
2101 } 2146 chunk->num_pcm = samp_per_frame;
2102 } 2147 }
2103 2148
2104 /* encode one mp3 frame in this loop */ 2149 if (cfg.channels == 1)
2105 CodedData.bitpos = 0; 2150 to_mono_mm();
2106 memset(CodedData.bbuf, 0, sizeof(CodedData.bbuf));
2107
2108 if((cfg.slot_lag += cfg.frac_per_frame) >= 64)
2109 { /* Padding for this frame */
2110 cfg.slot_lag -= 64;
2111 cfg.mpg.padding = 1;
2112 }
2113 else
2114 cfg.mpg.padding = 0;
2115 2151
2116 cfg.mean_bits = (8 * cfg.byte_per_frame + 8 * cfg.mpg.padding 2152 cfg.ResvSize = 0;
2117 - cfg.sideinfo_len) / cfg.granules / cfg.channels; 2153 gr_cnt = cfg.granules * cfg.channels;
2154 CodedData.bitpos = cfg.sideinfo_len; /* leave space for mp3 header */
2118 2155
2119 /* shift out old samples */ 2156 for(gr=0; gr<cfg.granules; gr++)
2120 memcpy(mfbuf, mfbuf + 2*cfg.granules*576, 4*512); 2157 {
2121 /* read new samples to iram for further processing */ 2158 short *wk = mfbuf + 2*286 + gr*1152;
2122 memcpy((uint32*)(mfbuf + 2*512), buffer, 4*SAMP_PER_FRAME); 2159 int ch;
2123 2160
2124 if(cfg.resample) /* downsample to half of original */ 2161 /* 16bit packed wav data can be windowed efficiently on coldfire */
2125 for(i=2*512; i<2*512+2*SAMP_PER_FRAME; i+=4) 2162 window_subband1(wk, sb_data[0][1-gr][0], sb_data[1][1-gr][0]);
2126 {
2127 mfbuf[i/2+512] = (short)(((int)mfbuf[i+0] + mfbuf[i+2]) >> 1);
2128 mfbuf[i/2+513] = (short)(((int)mfbuf[i+1] + mfbuf[i+3]) >> 1);
2129 }
2130 2163
2131 if(cfg.channels == 1) /* mix left and right channels to mono */ 2164 for(ch=0; ch<cfg.channels; ch++)
2132 for(i=2*512; i<2*512+2*SAMP_PER_FRAME; i+=2) 2165 {
2133 mfbuf[i] = mfbuf[i+1] = (short)(((int)mfbuf[i] + mfbuf[i+1]) >> 1); 2166 int ii, k, shift;
2134 2167
2135 cfg.ResvSize = 0; 2168 wk = mfbuf + 2*286 + gr*1152 + ch;
2136 gr_cnt = cfg.granules * cfg.channels;
2137 CodedData.bitpos = cfg.sideinfo_len; /* leave space for mp3 header */
2138 2169
2139 for(gr=0; gr<cfg.granules; gr++) 2170 /* 36864=4*18*16*32 */
2171 for(k=0; k<18; k++, wk+=64)
2140 { 2172 {
2141 short *wk = mfbuf + 2*286 + gr*1152; 2173 window_subband2(wk, sb_data[ch][1-gr][k]);
2142 2174 /* Compensate for inversion in the analysis filter */
2143 /* 16bit packed wav data can be windowed efficiently on coldfire */ 2175 if(k & 1)
2144 window_subband1(wk, sb_data[0][1-gr][0], sb_data[1][1-gr][0]);
2145
2146 for(ch=0; ch<cfg.channels; ch++)
2147 {
2148 int band;
2149 int *mdct;
2150
2151 wk = mfbuf + 2*286 + gr*1152 + ch;
2152
2153 /* 36864=4*18*16*32 */
2154 for(k=0; k<18; k++, wk+=64)
2155 { 2176 {
2156 window_subband2(wk, sb_data[ch][1-gr][k]); 2177 int band;
2157 /* Compensate for inversion in the analysis filter */
2158 if(k & 1)
2159 for(band=1; band<32; band+=2) 2178 for(band=1; band<32; band+=2)
2160 sb_data[ch][1-gr][k][band] *= -1; 2179 sb_data[ch][1-gr][k][band] *= -1;
2161 } 2180 }
2181 }
2162 2182
2163 /* Perform imdct of 18 previous + 18 current subband samples */ 2183 /* Perform imdct of 18 previous + 18 current subband samples
2164 /* for integer precision do this loop twice (if neccessary) */ 2184 for integer precision do this loop twice (if neccessary)
2165 shift = k = 14; 2185 */
2166 for(ii=0; ii<2 && k; ii++) 2186 shift = k = 14;
2187 for(ii=0; ii<2 && k; ii++)
2188 {
2189 int *mdct = mdct_freq;
2190 int band;
2191
2192 cfg.cod_info[gr][ch].additStep = 4 * (14 - shift);
2193
2194 for(band=0; band<cfg.mpg.num_bands; band++, mdct+=18)
2167 { 2195 {
2168 mdct = mdct_freq;
2169 cfg.cod_info[gr][ch].additStep = 4 * (14 - shift);
2170 for(band=0; band<cfg.mpg.num_bands; band++, mdct+=18)
2171 {
2172 int *band0 = sb_data[ch][ gr][0] + order[band]; 2196 int *band0 = sb_data[ch][ gr][0] + order[band];
2173 int *band1 = sb_data[ch][1-gr][0] + order[band]; 2197 int *band1 = sb_data[ch][1-gr][0] + order[band];
2174 int work[18]; 2198 int work[18];
@@ -2176,16 +2200,20 @@ enum codec_status codec_start(struct codec_api* api)
2176 /* 9216=4*32*9*8 */ 2200 /* 9216=4*32*9*8 */
2177 for(k=-9; k<0; k++) 2201 for(k=-9; k<0; k++)
2178 { 2202 {
2179 int a = shft_n(band1[(k+9)*32], shift); 2203 int a = shft_n(band1[(k+9)*32], shift);
2180 int b = shft_n(band1[(8-k)*32], shift); 2204 int b = shft_n(band1[(8-k)*32], shift);
2181 int c = shft_n(band0[(k+9)*32], shift); 2205 int c = shft_n(band0[(k+9)*32], shift);
2182 int d = shft_n(band0[(8-k)*32], shift); 2206 int d = shft_n(band0[(8-k)*32], shift);
2183 2207
2184 work[k+ 9] = shft16(a * win[k+ 9][0] + b * win[k+ 9][1] 2208 work[k+ 9] = shft16(a * win[k+ 9][0] +
2185 + c * win[k+ 9][2] + d * win[k+ 9][3]); 2209 b * win[k+ 9][1] +
2186 2210 c * win[k+ 9][2] +
2187 work[k+18] = shft16(c * win[k+18][0] + d * win[k+18][1] 2211 d * win[k+ 9][3]);
2188 + a * win[k+18][2] + b * win[k+18][3]); 2212
2213 work[k+18] = shft16(c * win[k+18][0] +
2214 d * win[k+18][1] +
2215 a * win[k+18][2] +
2216 b * win[k+18][3]);
2189 } 2217 }
2190 2218
2191 /* 7200=4*18*100 */ 2219 /* 7200=4*18*100 */
@@ -2193,67 +2221,309 @@ enum codec_status codec_start(struct codec_api* api)
2193 2221
2194 /* Perform aliasing reduction butterfly */ 2222 /* Perform aliasing reduction butterfly */
2195 if(band != 0) 2223 if(band != 0)
2196 for(k=7; k>=0; --k) 2224 {
2197 { 2225 for(k=7; k>=0; --k)
2198 int bu, bd; 2226 {
2199 bu = shft15(mdct[k]) * ca[k] + shft15(mdct[-1-k]) * cs[k]; 2227 int bu, bd;
2200 bd = shft15(mdct[k]) * cs[k] - shft15(mdct[-1-k]) * ca[k]; 2228 bu = shft15(mdct[k]) * ca[k] +
2201 mdct[-1-k] = bu; 2229 shft15(mdct[-1-k]) * cs[k];
2202 mdct[ k ] = bd; 2230 bd = shft15(mdct[k]) * cs[k] -
2203 } 2231 shft15(mdct[-1-k]) * ca[k];
2204 } 2232 mdct[-1-k] = bu;
2205 2233 mdct[ k ] = bd;
2206 max = min = 0; 2234 }
2207 for(k=0; k<576; k++) 2235 }
2208 { 2236 }
2237
2238 max = min = 0;
2239 for(k=0; k<576; k++)
2240 {
2209 mdct_freq[k] = shft13(mdct_freq[k]); 2241 mdct_freq[k] = shft13(mdct_freq[k]);
2210 if(max < mdct_freq[k]) max = mdct_freq[k]; 2242 if(max < mdct_freq[k]) max = mdct_freq[k];
2211 if(min > mdct_freq[k]) min = mdct_freq[k]; 2243 if(min > mdct_freq[k]) min = mdct_freq[k];
2212 } 2244 }
2213 2245
2214 max = (max > -min) ? max : -min; 2246 max = (max > -min) ? max : -min;
2215 cfg.cod_info[gr][ch].max_val = (long)max; 2247 cfg.cod_info[gr][ch].max_val = (long)max;
2216 2248
2217 /* calc new shift for higher integer precision */ 2249 /* calc new shift for higher integer precision */
2218 for(k=0; max<(0x3c00>>k); k++); 2250 for(k=0; max<(0x3c00>>k); k++);
2219 shift = 12 - k; 2251 shift = 12 - k;
2220 } 2252 }
2221 2253
2222 cfg.cod_info[gr][ch].quantStep += cfg.cod_info[gr][ch].additStep; 2254 cfg.cod_info[gr][ch].quantStep +=
2255 cfg.cod_info[gr][ch].additStep;
2223 2256
2224 /* bit and noise allocation */ 2257 /* bit and noise allocation */
2225 iteration_loop(mdct_freq, &cfg.cod_info[gr][ch], gr_cnt--); 2258 iteration_loop(mdct_freq, &cfg.cod_info[gr][ch],
2226 /* write the frame to the bitstream */ 2259 gr_cnt--);
2227 Huffmancodebits(enc_data, mdct_freq, &cfg.cod_info[gr][ch]); 2260 /* write the frame to the bitstream */
2261 Huffmancodebits(enc_data, mdct_freq,
2262 &cfg.cod_info[gr][ch]);
2228 2263
2229 cfg.cod_info[gr][ch].quantStep -= cfg.cod_info[gr][ch].additStep; 2264 cfg.cod_info[gr][ch].quantStep -=
2265 cfg.cod_info[gr][ch].additStep;
2230 2266
2231 if(cfg.granules == 1) 2267 if(cfg.granules == 1)
2232 memcpy(sb_data[ch][0], sb_data[ch][1], sizeof(sb_data[ch][0])); 2268 {
2233 } 2269 memcpy(sb_data[ch][0], sb_data[ch][1],
2270 sizeof(sb_data[ch][0]));
2234 } 2271 }
2272 }
2273 }
2274
2275 chunk->enc_size = cfg.byte_per_frame + cfg.mpg.padding;
2235 2276
2236 mp3_chunk_ptr = (uint32*)ci->enc_alloc_chunk();
2237 mp3_chunk_ptr[0] = cfg.byte_per_frame + cfg.mpg.padding; //(CodedData.bitpos + 7) >> 3;
2238 /* finish this chunk by adding sideinfo header data */ 2277 /* finish this chunk by adding sideinfo header data */
2239 CodedData.bitpos = 0; 2278 CodedData.bitpos = 0;
2240 encodeSideInfo( cfg.cod_info ); 2279 encodeSideInfo( cfg.cod_info );
2241 2280
2242 /* allocate mp3 chunk, set chunk size, copy chunk to enc_buffer */ 2281#ifdef ROCKBOX_BIG_ENDIAN
2243 memcpy(&mp3_chunk_ptr[1], CodedData.bbuf, mp3_chunk_ptr[0]); 2282 /* copy chunk to enc_buffer */
2244 ci->enc_free_chunk(); 2283 memcpy(chunk->enc_data, CodedData.bbuf, chunk->enc_size);
2284#else
2285 /* swap frame to big endian */
2286 byte_swap_frame32(chunk->enc_data, CodedData.bbuf, chunk->enc_size);
2287#endif
2288} /* encode_frame */
2289
2290/* called very often - inline */
2291static inline bool is_file_data_ok(struct enc_file_event_data *filed) ICODE_ATTR;
2292static inline bool is_file_data_ok(struct enc_file_event_data *filed)
2293{
2294 return filed->rec_file >= 0 && (long)filed->chunk->flags >= 0;
2295} /* is_event_ok */
2245 2296
2246 ci->yield(); 2297/* called very often - inline */
2298static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
2299static inline bool on_write_chunk(struct enc_file_event_data *data)
2300{
2301 if (!is_file_data_ok(data))
2302 return false;
2303
2304 if (data->chunk->enc_data == NULL)
2305 {
2306#ifdef ROCKBOX_HAS_LOGF
2307 ci->logf("mp3 enc: NULL data");
2308#endif
2309 return true;
2310 }
2311
2312 if (ci->write(data->rec_file, data->chunk->enc_data,
2313 data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
2314 return false;
2315
2316 data->num_pcm_samples += data->chunk->num_pcm;
2317 return true;
2318} /* on_write_chunk */
2319
2320static bool on_start_file(struct enc_file_event_data *data)
2321{
2322 if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
2323 return false;
2324
2325 data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC);
2326
2327 if (data->rec_file < 0)
2328 return false;
2329
2330 /* reset sample count */
2331 data->num_pcm_samples = 0;
2332 return true;
2333} /* on_start_file */
2334
2335static bool on_end_file(struct enc_file_event_data *data)
2336{
2337 if (!is_file_data_ok(data))
2338 return false;
2339
2340 ci->fsync(data->rec_file);
2341 ci->close(data->rec_file);
2342 data->rec_file = -1;
2343
2344 return true;
2345} /* on_end_file */
2346
2347static void on_rec_new_stream(struct enc_buffer_event_data *data)
2348{
2349 int num_frames = cfg.mpg.type == 1 ?
2350 ENC_PADDING_FRAMES1 : ENC_PADDING_FRAMES2;
2351
2352 if (data->flags & CHUNKF_END_FILE)
2353 {
2354 /* add silent frames to end - encoder will also be flushed for start
2355 of next file if any */
2356 memset(res_buffer, 0, pcm_chunk_size);
2357
2358 /* the initial chunk given for the end is at enc_wr_index */
2359 while (num_frames-- > 0)
2360 {
2361 data->chunk->enc_data = ENC_CHUNK_SKIP_HDR(data->chunk->enc_data,
2362 data->chunk);
2363
2364 encode_frame(res_buffer, data->chunk);
2365 data->chunk->num_pcm = samp_per_frame;
2366
2367 ci->enc_finish_chunk();
2368 data->chunk = ci->enc_get_chunk();
2247 } 2369 }
2370 }
2371 else if (data->flags & CHUNKF_PRERECORD)
2372 {
2373 /* nothing to add and we cannot change prerecorded data */
2374 }
2375 else if (data->flags & CHUNKF_START_FILE)
2376 {
2377 /* starting fresh ... be sure to flush encoder first */
2378 struct enc_chunk_hdr *chunk = ENC_CHUNK_HDR(res_buffer);
2248 2379
2249 if(ci->enc_wavbuf_near_empty()) 2380 chunk->flags = 0;
2381 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
2382
2383 while (num_frames-- > 0)
2250 { 2384 {
2251 if(cpu_boosted) 2385 memset(chunk->enc_data, 0, pcm_chunk_size);
2386 encode_frame(chunk->enc_data, chunk);
2387 }
2388 }
2389} /* on_rec_new_stream */
2390
2391static void enc_events_callback(enum enc_events event, void *data) ICODE_ATTR;
2392static void enc_events_callback(enum enc_events event, void *data)
2393{
2394 if (event == ENC_WRITE_CHUNK)
2395 {
2396 if (on_write_chunk((struct enc_file_event_data *)data))
2397 return;
2398 }
2399 else if (event == ENC_START_FILE)
2400 {
2401 if (on_start_file((struct enc_file_event_data *)data))
2402 return;
2403 }
2404 else if (event == ENC_END_FILE)
2405 {
2406 if (on_end_file((struct enc_file_event_data *)data))
2407 return;
2408 }
2409 else if (event == ENC_REC_NEW_STREAM)
2410 {
2411 on_rec_new_stream((struct enc_buffer_event_data *)data);
2412 return;
2413 }
2414 else
2415 {
2416 return;
2417 }
2418
2419 ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
2420} /* enc_events_callback */
2421
2422static bool enc_init(void)
2423{
2424 struct enc_inputs inputs;
2425 struct enc_parameters params;
2426
2427 if (ci->enc_get_inputs == NULL ||
2428 ci->enc_set_parameters == NULL ||
2429 ci->enc_get_chunk == NULL ||
2430 ci->enc_finish_chunk == NULL ||
2431 ci->enc_pcm_buf_near_empty == NULL ||
2432 ci->enc_get_pcm_data == NULL ||
2433 ci->enc_unget_pcm_data == NULL )
2434 return false;
2435
2436 ci->enc_get_inputs(&inputs);
2437
2438 if (inputs.config->afmt != AFMT_MPA_L3)
2439 return false;
2440
2441 init_mp3_encoder_engine(inputs.sample_rate, inputs.num_channels,
2442 inputs.config);
2443
2444 /* configure the buffer system */
2445 params.afmt = AFMT_MPA_L3;
2446 params.chunk_size = cfg.byte_per_frame + 1;
2447 params.enc_sample_rate = cfg.samplerate;
2448 /* need enough reserved bytes to hold one frame of pcm samples + hdr
2449 for padding and flushing */
2450 params.reserve_bytes = ENC_CHUNK_HDR_SIZE + pcm_chunk_size;
2451 params.events_callback = enc_events_callback;
2452 ci->enc_set_parameters(&params);
2453
2454 res_buffer = params.reserve_buffer;
2455
2456#ifdef CPU_COLDFIRE
2457 asm volatile ("move.l #0, %macsr"); /* integer mode */
2458#endif
2459
2460 return true;
2461} /* enc_init */
2462
2463enum codec_status codec_start(struct codec_api* api)
2464{
2465 bool cpu_boosted;
2466
2467 /* Generic codec initialisation */
2468 ci = api;
2469
2470#ifdef USE_IRAM
2471 memcpy(iramstart, iramcopy, iramend - iramstart);
2472 memset(iedata, 0, iend - iedata);
2473#endif
2474
2475 if (!enc_init())
2476 {
2477 ci->enc_codec_loaded = -1;
2478 return CODEC_ERROR;
2479 }
2480
2481 /* main application waits for this flag during encoder loading */
2482 ci->enc_codec_loaded = 1;
2483
2484 ci->cpu_boost(true);
2485 cpu_boosted = true;
2486
2487 /* main encoding loop */
2488 while (!ci->stop_codec)
2489 {
2490 char *buffer;
2491
2492 while ((buffer = ci->enc_get_pcm_data(pcm_chunk_size)) != NULL)
2493 {
2494 struct enc_chunk_hdr *chunk;
2495
2496 if (ci->stop_codec)
2497 break;
2498
2499 if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
2500 {
2501 ci->cpu_boost(true);
2502 cpu_boosted = true;
2503 }
2504
2505 chunk = ci->enc_get_chunk();
2506 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
2507
2508 encode_frame(buffer, chunk);
2509
2510 if (chunk->num_pcm < samp_per_frame)
2511 {
2512 ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4);
2513 chunk->num_pcm = samp_per_frame;
2514 }
2515
2516 ci->enc_finish_chunk();
2517
2518 ci->yield();
2519 }
2520
2521 if (cpu_boosted && ci->enc_pcm_buf_near_empty())
2252 { 2522 {
2253 ci->cpu_boost(false); 2523 ci->cpu_boost(false);
2254 cpu_boosted = false; 2524 cpu_boosted = false;
2255 } 2525 }
2256 } 2526
2257 ci->yield(); 2527 ci->yield();
2258 } 2528 }
2259 2529
@@ -2261,12 +2531,12 @@ enum codec_status codec_start(struct codec_api* api)
2261 ci->cpu_boost(false); 2531 ci->cpu_boost(false);
2262 2532
2263 /* reset parameters to initial state */ 2533 /* reset parameters to initial state */
2264 ci->enc_set_parameters(0, 0, 0, 0, 0, 0); 2534 ci->enc_set_parameters(NULL);
2265 2535
2266 /* main application waits for this flag during encoder removing */ 2536 /* main application waits for this flag during encoder removing */
2267 ci->enc_codec_loaded = false; 2537 ci->enc_codec_loaded = 0;
2268 2538
2269 return CODEC_OK; 2539 return CODEC_OK;
2270} 2540} /* codec_start */
2271 2541
2272#endif 2542#endif /* ndef SIMULATOR */
diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c
index 5aabb5d8e8..974a903310 100644
--- a/apps/codecs/wav_enc.c
+++ b/apps/codecs/wav_enc.c
@@ -19,140 +19,364 @@
19 19
20#ifndef SIMULATOR 20#ifndef SIMULATOR
21 21
22#include <inttypes.h>
22#include "codeclib.h" 23#include "codeclib.h"
23 24
24CODEC_HEADER 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 riff_header
36{
37 uint8_t riff_id[4]; /* 00h - "RIFF" */
38 uint32_t riff_size; /* 04h - sz following headers + data_size */
39 /* format header */
40 uint8_t format[4]; /* 08h - "WAVE" */
41 uint8_t format_id[4]; /* 0Ch - "fmt " */
42 uint32_t format_size; /* 10h - 16 for PCM (sz format data) */
43 /* format data */
44 uint16_t audio_format; /* 14h - 1=PCM */
45 uint16_t num_channels; /* 16h - 1=M, 2=S, etc. */
46 uint32_t sample_rate; /* 18h - HZ */
47 uint32_t byte_rate; /* 1Ch - num_channels*sample_rate*bits_per_sample/8 */
48 uint16_t block_align; /* 20h - num_channels*bits_per_samples/8 */
49 uint16_t bits_per_sample; /* 22h - 8=8 bits, 16=16 bits, etc. */
50 /* Not for audio_format=1 (PCM) */
51/* unsigned short extra_param_size; 24h - size of extra data */
52/* unsigned char *extra_params; */
53 /* data header */
54 uint8_t data_id[4]; /* 24h - "data" */
55 uint32_t data_size; /* 28h - num_samples*num_channels*bits_per_sample/8 */
56/* unsigned char *data; 2ch - actual sound data */
57};
58
59#define RIFF_FMT_HEADER_SIZE 12 /* format -> format_size */
60#define RIFF_FMT_DATA_SIZE 16 /* audio_format -> bits_per_sample */
61#define RIFF_DATA_HEADER_SIZE 8 /* data_id -> data_size */
62
63#define PCM_DEPTH_BYTES 2
64#define PCM_DEPTH_BITS 16
65#define PCM_SAMP_PER_CHUNK 2048
66#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
25 67
26static struct codec_api *ci; 68static struct codec_api *ci;
27static int enc_channels; 69static int num_channels;
70uint32_t sample_rate;
71uint32_t enc_size;
28 72
29#define CHUNK_SIZE 8192 73static const struct riff_header riff_header =
74{
75 /* "RIFF" header */
76 { 'R', 'I', 'F', 'F' }, /* riff_id */
77 0, /* riff_size (*) */
78 /* format header */
79 { 'W', 'A', 'V', 'E' }, /* format */
80 { 'f', 'm', 't', ' ' }, /* format_id */
81 H_TO_LE32(16), /* format_size */
82 /* format data */
83 H_TO_LE16(1), /* audio_format */
84 0, /* num_channels (*) */
85 0, /* sample_rate (*) */
86 0, /* byte_rate (*) */
87 0, /* block_align (*) */
88 H_TO_LE16(PCM_DEPTH_BITS), /* bits_per_sample */
89 /* data header */
90 { 'd', 'a', 't', 'a' }, /* data_id */
91 0 /* data_size (*) */
92 /* (*) updated during ENC_END_FILE event */
93};
30 94
31static unsigned char wav_header[44] = 95/* called version often - inline */
32{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16, 96static inline bool is_file_data_ok(struct enc_file_event_data *data) ICODE_ATTR;
33 0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0}; 97static inline bool is_file_data_ok(struct enc_file_event_data *data)
98{
99 return data->rec_file >= 0 && (long)data->chunk->flags >= 0;
100} /* is_file_data_ok */
34 101
35static unsigned char wav_header_mono[44] = 102/* called version often - inline */
36{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16, 103static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
37 0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0}; 104static inline bool on_write_chunk(struct enc_file_event_data *data)
105{
106 if (!is_file_data_ok(data))
107 return false;
38 108
39/* update file header info callback function (called by main application) */ 109 if (data->chunk->enc_data == NULL)
40void enc_set_header(void *head_buffer, /* ptr to the file header data */ 110 {
41 int head_size, /* size of this header data */ 111#ifdef ROCKBOX_HAS_LOGF
42 int num_pcm_samples, /* amount of processed pcm samples */ 112 ci->logf("wav enc: NULL data");
43 bool is_file_header) 113#endif
114 return true;
115 }
116
117 if (ci->write(data->rec_file, data->chunk->enc_data,
118 data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
119 return false;
120
121 data->num_pcm_samples += data->chunk->num_pcm;
122 return true;
123} /* on_write_chunk */
124
125static bool on_start_file(struct enc_file_event_data *data)
44{ 126{
45 int num_file_bytes = num_pcm_samples * 2 * enc_channels; 127 if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
128 return false;
129
130 data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC);
131
132 if (data->rec_file < 0)
133 return false;
134
135 /* reset sample count */
136 data->num_pcm_samples = 0;
46 137
47 if(is_file_header) 138 /* write template header */
139 if (ci->write(data->rec_file, &riff_header, sizeof (riff_header))
140 != sizeof (riff_header))
48 { 141 {
49 /* update file header before file closing */ 142 return false;
50 if((int)sizeof(wav_header) < head_size) 143 }
144
145 data->new_enc_size += sizeof (riff_header);
146 return true;
147} /* on_start_file */
148
149static bool on_end_file(struct enc_file_event_data *data)
150{
151 /* update template header */
152 struct riff_header hdr;
153 uint32_t data_size;
154
155 if (!is_file_data_ok(data))
156 return false;
157
158 if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
159 ci->read(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr))
160 {
161 return false;
162 }
163
164 data_size = data->num_pcm_samples*num_channels*PCM_DEPTH_BYTES;
165
166 /* "RIFF" header */
167 hdr.riff_size = htole32(RIFF_FMT_HEADER_SIZE + RIFF_FMT_DATA_SIZE
168 + RIFF_DATA_HEADER_SIZE + data_size);
169
170 /* format data */
171 hdr.num_channels = htole16(num_channels);
172 hdr.sample_rate = htole32(sample_rate);
173 hdr.byte_rate = htole32(sample_rate*num_channels* PCM_DEPTH_BYTES);
174 hdr.block_align = htole16(num_channels*PCM_DEPTH_BYTES);
175
176 /* data header */
177 hdr.data_size = htole32(data_size);
178
179 if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
180 ci->write(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr))
181 {
182 return false;
183 }
184
185 ci->fsync(data->rec_file);
186 ci->close(data->rec_file);
187 data->rec_file = -1;
188
189 return true;
190} /* on_end_file */
191
192static void enc_events_callback(enum enc_events event, void *data) ICODE_ATTR;
193static void enc_events_callback(enum enc_events event, void *data)
194{
195 if (event == ENC_WRITE_CHUNK)
196 {
197 if (on_write_chunk((struct enc_file_event_data *)data))
198 return;
199 }
200 else if (event == ENC_START_FILE)
201 {
202 if (on_start_file((struct enc_file_event_data *)data))
203 return;
204 }
205 else if (event == ENC_END_FILE)
206 {
207 if (on_end_file((struct enc_file_event_data *)data))
208 return;
209 }
210 else
211 {
212 return;
213 }
214
215 ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
216} /* enc_events_callback */
217
218/* convert native pcm samples to wav format samples */
219static void chunk_to_wav_format(uint32_t *src, uint32_t *dst) ICODE_ATTR;
220static void chunk_to_wav_format(uint32_t *src, uint32_t *dst)
221{
222 if (num_channels == 1)
223 {
224 /* On big endian:
225 * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
226 * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
227 * |mmmmmmmmMMMMMMMM|mmmmmmmmMMMMMMMM|
228 *
229 * On little endian:
230 * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
231 * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
232 * |mmmmmmmmMMMMMMMM|mmmmmmmmMMMMMMMM|
233 */
234 uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
235
236 inline void to_mono(uint32_t **src, uint32_t **dst)
51 { 237 {
52 /* update wave header size entries: special to WAV format */ 238 int32_t lr1, lr2;
53 *(long*)(head_buffer+ 4) = htole32(num_file_bytes + 36); 239
54 *(long*)(head_buffer+40) = htole32(num_file_bytes); 240 lr1 = *(*src)++;
241 lr1 = ((int16_t)lr1 + (lr1 >> 16)) >> 1;
242
243 lr2 = *(*src)++;
244 lr2 = ((int16_t)lr2 + (lr2 >> 16)) >> 1;
245 *(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
246 } /* to_mono */
247
248 do
249 {
250 to_mono(&src, &dst);
251 to_mono(&src, &dst);
252 to_mono(&src, &dst);
253 to_mono(&src, &dst);
254 to_mono(&src, &dst);
255 to_mono(&src, &dst);
256 to_mono(&src, &dst);
257 to_mono(&src, &dst);
55 } 258 }
259 while (src < src_end);
56 } 260 }
57} 261 else
262 {
263#ifdef ROCKBOX_BIG_ENDIAN
264 /* |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
265 * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
266 */
267 uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
58 268
59/* main codec entry point */ 269 do
60enum codec_status codec_start(struct codec_api* api) 270 {
271 *dst++ = swap_odd_even32(*src++);
272 *dst++ = swap_odd_even32(*src++);
273 *dst++ = swap_odd_even32(*src++);
274 *dst++ = swap_odd_even32(*src++);
275 *dst++ = swap_odd_even32(*src++);
276 *dst++ = swap_odd_even32(*src++);
277 *dst++ = swap_odd_even32(*src++);
278 *dst++ = swap_odd_even32(*src++);
279 }
280 while (src < src_end);
281#else
282 /* |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
283 * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
284 */
285 ci->memcpy(dst, src, PCM_CHUNK_SIZE);
286#endif
287 }
288} /* chunk_to_wav_format */
289
290static bool init_encoder(void)
61{ 291{
62 int i; 292 struct enc_inputs inputs;
63 long lr; 293 struct enc_parameters params;
64 unsigned long t;
65 unsigned long *src;
66 unsigned long *dst;
67 int chunk_size, num_chunks, samp_per_chunk;
68 int enc_buffer_size;
69 int enc_quality;
70 bool cpu_boosted = true; /* start boosted */
71 294
72 ci = api; // copy to global api pointer 295 if (ci->enc_get_inputs == NULL ||
296 ci->enc_set_parameters == NULL ||
297 ci->enc_get_chunk == NULL ||
298 ci->enc_finish_chunk == NULL ||
299 ci->enc_pcm_buf_near_empty == NULL ||
300 ci->enc_get_pcm_data == NULL )
301 return false;
73 302
74 if(ci->enc_get_inputs == NULL || 303 ci->enc_get_inputs(&inputs);
75 ci->enc_set_parameters == NULL ||
76 ci->enc_alloc_chunk == NULL ||
77 ci->enc_free_chunk == NULL ||
78 ci->enc_wavbuf_near_empty == NULL ||
79 ci->enc_get_wav_data == NULL ||
80 ci->enc_set_header_callback == NULL )
81 return CODEC_ERROR;
82 304
83 ci->cpu_boost(true); 305 if (inputs.config->afmt != AFMT_PCM_WAV)
306 return false;
84 307
85 *ci->enc_set_header_callback = enc_set_header; 308 sample_rate = inputs.sample_rate;
86 ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality); 309 num_channels = inputs.num_channels;
87 310
88 /* configure the buffer system */ 311 /* configure the buffer system */
89 chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2; 312 params.afmt = AFMT_PCM_WAV;
90 num_chunks = enc_buffer_size / chunk_size; 313 enc_size = PCM_CHUNK_SIZE*inputs.num_channels / 2;
91 samp_per_chunk = CHUNK_SIZE / 4; 314 params.chunk_size = enc_size;
315 params.enc_sample_rate = sample_rate;
316 params.reserve_bytes = 0;
317 params.events_callback = enc_events_callback;
318 ci->enc_set_parameters(&params);
319
320 return true;
321} /* init_encoder */
322
323/* main codec entry point */
324enum codec_status codec_start(struct codec_api* api)
325{
326 bool cpu_boosted;
92 327
93 /* inform the main program about buffer dimensions and other params */ 328 ci = api; // copy to global api pointer
94 ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk, 329
95 (enc_channels == 2) ? wav_header : wav_header_mono, 330#ifdef USE_IRAM
96 sizeof(wav_header), AFMT_PCM_WAV); 331 ci->memcpy(iramstart, iramcopy, iramend - iramstart);
332 ci->memset(iedata, 0, iend - iedata);
333#endif
334
335 if (!init_encoder())
336 {
337 ci->enc_codec_loaded = -1;
338 return CODEC_ERROR;
339 }
97 340
98 /* main application waits for this flag during encoder loading */ 341 /* main application waits for this flag during encoder loading */
99 ci->enc_codec_loaded = true; 342 ci->enc_codec_loaded = 1;
343
344 ci->cpu_boost(true);
345 cpu_boosted = true;
100 346
101 /* main encoding loop */ 347 /* main encoding loop */
102 while(!ci->stop_codec) 348 while(!ci->stop_codec)
103 { 349 {
104 while((src = (unsigned long*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL) 350 uint32_t *src;
351
352 while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL)
105 { 353 {
106 if(ci->stop_codec) 354 struct enc_chunk_hdr *chunk;
355
356 if (ci->stop_codec)
107 break; 357 break;
108 358
109 if(ci->enc_wavbuf_near_empty() == 0) 359 if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
110 { 360 {
111 if(!cpu_boosted) 361 ci->cpu_boost(true);
112 { 362 cpu_boosted = true;
113 ci->cpu_boost(true);
114 cpu_boosted = true;
115 }
116 } 363 }
117 364
118 dst = (unsigned long*)ci->enc_alloc_chunk(); 365 chunk = ci->enc_get_chunk();
119 *dst++ = CHUNK_SIZE * enc_channels / 2; /* set size info */ 366 chunk->enc_size = enc_size;
367 chunk->num_pcm = PCM_SAMP_PER_CHUNK;
368 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
120 369
121 if(enc_channels == 2) 370 chunk_to_wav_format(src, (uint32_t *)chunk->enc_data);
122 {
123 /* swap byte order & copy to destination */
124 for (i=0; i<CHUNK_SIZE/4; i++)
125 {
126 t = *src++;
127 *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
128 }
129 }
130 else
131 {
132 /* mix left/right, swap byte order & copy to destination */
133 for (i=0; i<CHUNK_SIZE/8; i++)
134 {
135 lr = (long)*src++;
136 lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
137 t = (lr << 16);
138 lr = (long)*src++;
139 lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
140 t |= lr & 0xffff;
141 *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
142 }
143 }
144 371
145 ci->enc_free_chunk(); 372 ci->enc_finish_chunk();
146 ci->yield(); 373 ci->yield();
147 } 374 }
148 375
149 if(ci->enc_wavbuf_near_empty()) 376 if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
150 { 377 {
151 if(cpu_boosted) 378 ci->cpu_boost(false);
152 { 379 cpu_boosted = false;
153 ci->cpu_boost(false);
154 cpu_boosted = false;
155 }
156 } 380 }
157 381
158 ci->yield(); 382 ci->yield();
@@ -162,11 +386,12 @@ enum codec_status codec_start(struct codec_api* api)
162 ci->cpu_boost(false); 386 ci->cpu_boost(false);
163 387
164 /* reset parameters to initial state */ 388 /* reset parameters to initial state */
165 ci->enc_set_parameters(0, 0, 0, 0, 0, 0); 389 ci->enc_set_parameters(NULL);
166 390
167 /* main application waits for this flag during encoder removing */ 391 /* main application waits for this flag during encoder removing */
168 ci->enc_codec_loaded = false; 392 ci->enc_codec_loaded = 0;
169 393
170 return CODEC_OK; 394 return CODEC_OK;
171} 395} /* codec_start */
172#endif 396
397#endif /* ndef SIMULATOR */
diff --git a/apps/codecs/wavpack_enc.c b/apps/codecs/wavpack_enc.c
index eced7f1f4e..5318abc8fb 100644
--- a/apps/codecs/wavpack_enc.c
+++ b/apps/codecs/wavpack_enc.c
@@ -22,201 +22,474 @@
22#include "codeclib.h" 22#include "codeclib.h"
23#include "libwavpack/wavpack.h" 23#include "libwavpack/wavpack.h"
24 24
25CODEC_HEADER 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
26 34
27typedef unsigned long uint32; 35/** Types **/
28typedef unsigned short uint16; 36typedef struct
29typedef unsigned char uint8; 37{
38 uint8_t type; /* Type of metadata */
39 uint8_t word_size; /* Size of metadata in words */
40} WavpackMetadataHeader;
30 41
31static unsigned char wav_header_ster [46] = 42struct riff_header
32{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16, 43{
33 0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0}; 44 uint8_t riff_id[4]; /* 00h - "RIFF" */
45 uint32_t riff_size; /* 04h - sz following headers + data_size */
46 /* format header */
47 uint8_t format[4]; /* 08h - "WAVE" */
48 uint8_t format_id[4]; /* 0Ch - "fmt " */
49 uint32_t format_size; /* 10h - 16 for PCM (sz format data) */
50 /* format data */
51 uint16_t audio_format; /* 14h - 1=PCM */
52 uint16_t num_channels; /* 16h - 1=M, 2=S, etc. */
53 uint32_t sample_rate; /* 18h - HZ */
54 uint32_t byte_rate; /* 1Ch - num_channels*sample_rate*bits_per_sample/8 */
55 uint16_t block_align; /* 20h - num_channels*bits_per_samples/8 */
56 uint16_t bits_per_sample; /* 22h - 8=8 bits, 16=16 bits, etc. */
57 /* Not for audio_format=1 (PCM) */
58/* unsigned short extra_param_size; 24h - size of extra data */
59/* unsigned char *extra_params; */
60 /* data header */
61 uint8_t data_id[4]; /* 24h - "data" */
62 uint32_t data_size; /* 28h - num_samples*num_channels*bits_per_sample/8 */
63/* unsigned char *data; 2ch - actual sound data */
64};
65
66#define RIFF_FMT_HEADER_SIZE 12 /* format -> format_size */
67#define RIFF_FMT_DATA_SIZE 16 /* audio_format -> bits_per_sample */
68#define RIFF_DATA_HEADER_SIZE 8 /* data_id -> data_size */
69
70#define PCM_DEPTH_BITS 16
71#define PCM_DEPTH_BYTES 2
72#define PCM_SAMP_PER_CHUNK 5000
73#define PCM_CHUNK_SIZE (4*PCM_SAMP_PER_CHUNK)
74
75/** Data **/
76static struct codec_api *ci;
77static int8_t input_buffer[PCM_CHUNK_SIZE*2] IBSS_ATTR;
78static WavpackConfig config IBSS_ATTR;
79static WavpackContext *wpc;
80static int32_t data_size, input_size, input_step IBSS_ATTR;
34 81
35static unsigned char wav_header_mono [46] = 82static const WavpackMetadataHeader wvpk_mdh =
36{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16, 83{
37 0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0}; 84 ID_RIFF_HEADER,
85 sizeof (struct riff_header) / sizeof (uint16_t),
86};
38 87
39static struct codec_api *ci; 88static const struct riff_header riff_header =
40static int enc_channels; 89{
90 /* "RIFF" header */
91 { 'R', 'I', 'F', 'F' }, /* riff_id */
92 0, /* riff_size (*) */
93 /* format header */
94 { 'W', 'A', 'V', 'E' }, /* format */
95 { 'f', 'm', 't', ' ' }, /* format_id */
96 H_TO_LE32(16), /* format_size */
97 /* format data */
98 H_TO_LE16(1), /* audio_format */
99 0, /* num_channels (*) */
100 0, /* sample_rate (*) */
101 0, /* byte_rate (*) */
102 0, /* block_align (*) */
103 H_TO_LE16(PCM_DEPTH_BITS), /* bits_per_sample */
104 /* data header */
105 { 'd', 'a', 't', 'a' }, /* data_id */
106 0 /* data_size (*) */
107 /* (*) updated during ENC_END_FILE event */
108};
109
110static void chunk_to_int32(int32_t *src) ICODE_ATTR;
111static void chunk_to_int32(int32_t *src)
112{
113 int32_t *dst = (int32_t *)input_buffer + PCM_SAMP_PER_CHUNK;
114 int32_t *src_end = dst + PCM_SAMP_PER_CHUNK;
41 115
42#define CHUNK_SIZE 20000 116 /* copy to IRAM before converting data */
117 memcpy(dst, src, PCM_CHUNK_SIZE);
43 118
44static long input_buffer[CHUNK_SIZE/2] IBSS_ATTR; 119 src = dst;
120 dst = (int32_t *)input_buffer;
45 121
46/* update file header info callback function */ 122 if (config.num_channels == 1)
47void enc_set_header(void *head_buffer, /* ptr to the file header data */
48 int head_size, /* size of this header data */
49 int num_pcm_sampl, /* amount of processed pcm samples */
50 bool is_file_header) /* update file/chunk header */
51{
52 if(is_file_header)
53 { 123 {
54 /* update file header before file closing */ 124 /*
55 if(sizeof(WavpackHeader) + sizeof(wav_header_mono) < (unsigned)head_size) 125 * |llllllllllllllll|rrrrrrrrrrrrrrrr| =>
126 * |mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm|
127 */
128 inline void to_int32(int32_t **src, int32_t **dst)
56 { 129 {
57 char* riff_header = (char*)head_buffer + sizeof(WavpackHeader); 130 int32_t t = *(*src)++;
58 char* wv_header = (char*)head_buffer + sizeof(wav_header_mono); 131 /* endianness irrelevant */
59 int num_file_bytes = num_pcm_sampl * 2 * enc_channels; 132 *(*dst)++ = ((int16_t)t + (t >> 16)) >> 1;
60 unsigned long ckSize; 133 } /* to_int32 */
61 134
62 /* RIFF header and WVPK header have to be swapped */ 135 do
63 /* copy wavpack header to file start position */ 136 {
64 ci->memcpy(head_buffer, wv_header, sizeof(WavpackHeader)); 137 /* read 10 longs and write 10 longs */
65 wv_header = head_buffer; /* recalc wavpack header position */ 138 to_int32(&src, &dst);
66 139 to_int32(&src, &dst);
67 if(enc_channels == 2) 140 to_int32(&src, &dst);
68 ci->memcpy(riff_header, wav_header_ster, sizeof(wav_header_ster)); 141 to_int32(&src, &dst);
69 else 142 to_int32(&src, &dst);
70 ci->memcpy(riff_header, wav_header_mono, sizeof(wav_header_mono)); 143 to_int32(&src, &dst);
71 144 to_int32(&src, &dst);
72 /* update the Wavpack header first chunk size & total frame count */ 145 to_int32(&src, &dst);
73 ckSize = htole32(((WavpackHeader*)wv_header)->ckSize) 146 to_int32(&src, &dst);
74 + sizeof(wav_header_mono); 147 to_int32(&src, &dst);
75 ((WavpackHeader*)wv_header)->total_samples = htole32(num_pcm_sampl);
76 ((WavpackHeader*)wv_header)->ckSize = htole32(ckSize);
77
78 /* update the RIFF WAV header size entries */
79 *(long*)(riff_header+ 6) = htole32(num_file_bytes + 36);
80 *(long*)(riff_header+42) = htole32(num_file_bytes);
81 } 148 }
149 while(src < src_end);
150
151 return;
82 } 152 }
83 else 153 else
84 { 154 {
85 /* update timestamp (block_index) */ 155 /*
86 ((WavpackHeader*)head_buffer)->block_index = htole32(num_pcm_sampl); 156 * |llllllllllllllll|rrrrrrrrrrrrrrrr| =>
157 * |llllllllllllllllllllllllllllllll|rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
158 */
159 inline void to_int32(int32_t **src, int32_t **dst)
160 {
161 int32_t t = *(*src)++;
162#ifdef ROCKBOX_BIG_ENDIAN
163 *(*dst)++ = t >> 16, *(*dst)++ = (int16_t)t;
164#else
165 *(*dst)++ = (int16_t)t, *(*dst)++ = t >> 16;
166#endif
167 } /* to_int32 */
168
169 do
170 {
171 /* read 10 longs and write 20 longs */
172 to_int32(&src, &dst);
173 to_int32(&src, &dst);
174 to_int32(&src, &dst);
175 to_int32(&src, &dst);
176 to_int32(&src, &dst);
177 to_int32(&src, &dst);
178 to_int32(&src, &dst);
179 to_int32(&src, &dst);
180 to_int32(&src, &dst);
181 to_int32(&src, &dst);
182 }
183 while (src < src_end);
184
185 return;
87 } 186 }
88} 187} /* chunk_to_int32 */
89 188
189/* called very often - inline */
190static inline bool is_file_data_ok(struct enc_file_event_data *data) ICODE_ATTR;
191static inline bool is_file_data_ok(struct enc_file_event_data *data)
192{
193 return data->rec_file >= 0 && (long)data->chunk->flags >= 0;
194} /* is_file_data_ok */
90 195
91enum codec_status codec_start(struct codec_api* api) 196/* called very often - inline */
197static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
198static inline bool on_write_chunk(struct enc_file_event_data *data)
199{
200 if (!is_file_data_ok(data))
201 return false;
202
203 if (data->chunk->enc_data == NULL)
204 {
205#ifdef ROCKBOX_HAS_LOGF
206 ci->logf("wvpk enc: NULL data");
207#endif
208 return true;
209 }
210
211 /* update timestamp (block_index) */
212 ((WavpackHeader *)data->chunk->enc_data)->block_index =
213 htole32(data->num_pcm_samples);
214
215 if (ci->write(data->rec_file, data->chunk->enc_data,
216 data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
217 return false;
218
219 data->num_pcm_samples += data->chunk->num_pcm;
220 return true;
221} /* on_write_chunk */
222
223static bool on_start_file(struct enc_file_event_data *data)
224{
225 if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
226 return false;
227
228 data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC);
229
230 if (data->rec_file < 0)
231 return false;
232
233 /* reset sample count */
234 data->num_pcm_samples = 0;
235
236 /* write template headers */
237 if (ci->write(data->rec_file, &wvpk_mdh, sizeof (wvpk_mdh))
238 != sizeof (wvpk_mdh) ||
239 ci->write(data->rec_file, &riff_header, sizeof (riff_header))
240 != sizeof (riff_header))
241 {
242 return false;
243 }
244
245 data->new_enc_size += sizeof(wvpk_mdh) + sizeof(riff_header);
246 return true;
247} /* on_start_file */
248
249static bool on_end_file(struct enc_file_event_data *data)
250{
251 struct
252 {
253 WavpackMetadataHeader wpmdh;
254 struct riff_header rhdr;
255 WavpackHeader wph;
256 } __attribute__ ((packed)) h;
257
258 uint32_t data_size;
259
260 if (!is_file_data_ok(data))
261 return false;
262
263 /* read template headers at start */
264 if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
265 ci->read(data->rec_file, &h, sizeof (h)) != sizeof (h))
266 return false;
267
268 data_size = data->num_pcm_samples*config.num_channels*PCM_DEPTH_BYTES;
269
270 /** "RIFF" header **/
271 h.rhdr.riff_size = htole32(RIFF_FMT_HEADER_SIZE +
272 RIFF_FMT_DATA_SIZE + RIFF_DATA_HEADER_SIZE + data_size);
273
274 /* format data */
275 h.rhdr.num_channels = htole16(config.num_channels);
276 h.rhdr.sample_rate = htole32(config.sample_rate);
277 h.rhdr.byte_rate = htole32(config.sample_rate*config.num_channels*
278 PCM_DEPTH_BYTES);
279 h.rhdr.block_align = htole16(config.num_channels*PCM_DEPTH_BYTES);
280
281 /* data header */
282 h.rhdr.data_size = htole32(data_size);
283
284 /** Wavpack header **/
285 h.wph.ckSize = htole32(letoh32(h.wph.ckSize) + sizeof (h.wpmdh)
286 + sizeof (h.rhdr));
287 h.wph.total_samples = htole32(data->num_pcm_samples);
288
289 /* MDH|RIFF|WVPK => WVPK|MDH|RIFF */
290 if (ci->lseek(data->rec_file, 0, SEEK_SET)
291 != 0 ||
292 ci->write(data->rec_file, &h.wph, sizeof (h.wph))
293 != sizeof (h.wph) ||
294 ci->write(data->rec_file, &h.wpmdh, sizeof (h.wpmdh))
295 != sizeof (h.wpmdh) ||
296 ci->write(data->rec_file, &h.rhdr, sizeof (h.rhdr))
297 != sizeof (h.rhdr))
298 {
299 return false;
300 }
301
302 ci->fsync(data->rec_file);
303 ci->close(data->rec_file);
304 data->rec_file = -1;
305
306 return true;
307} /* on_end_file */
308
309static void enc_events_callback(enum enc_events event, void *data) ICODE_ATTR;
310static void enc_events_callback(enum enc_events event, void *data)
92{ 311{
93 int i; 312 if (event == ENC_WRITE_CHUNK)
94 long t; 313 {
95 uint32 *src; 314 if (on_write_chunk((struct enc_file_event_data *)data))
96 uint32 *dst; 315 return;
97 int chunk_size, num_chunks, samp_per_chunk; 316 }
98 int enc_buffer_size; 317 else if (event == ENC_START_FILE)
99 int enc_quality; 318 {
100 WavpackConfig config; 319 /* write metadata header and RIFF header */
101 WavpackContext *wpc; 320 if (on_start_file((struct enc_file_event_data *)data))
102 bool cpu_boosted = true; /* start boosted */ 321 return;
103 322 }
104 ci = api; // copy to global api pointer 323 else if (event == ENC_END_FILE)
324 {
325 if (on_end_file((struct enc_file_event_data *)data))
326 return;
327 }
328 else
329 {
330 return;
331 }
332
333 ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
334} /* enc_events_callback */
335
336static bool init_encoder(void)
337{
338 struct enc_inputs inputs;
339 struct enc_parameters params;
105 340
106 codec_init(ci); 341 codec_init(ci);
107 342
108 if(ci->enc_get_inputs == NULL || 343 if (ci->enc_get_inputs == NULL ||
109 ci->enc_set_parameters == NULL || 344 ci->enc_set_parameters == NULL ||
110 ci->enc_alloc_chunk == NULL || 345 ci->enc_get_chunk == NULL ||
111 ci->enc_free_chunk == NULL || 346 ci->enc_finish_chunk == NULL ||
112 ci->enc_wavbuf_near_empty == NULL || 347 ci->enc_pcm_buf_near_empty == NULL ||
113 ci->enc_get_wav_data == NULL || 348 ci->enc_get_pcm_data == NULL ||
114 ci->enc_set_header_callback == NULL ) 349 ci->enc_unget_pcm_data == NULL )
115 return CODEC_ERROR; 350 return false;
116 351
117 ci->cpu_boost(true); 352 ci->enc_get_inputs(&inputs);
353
354 if (inputs.config->afmt != AFMT_WAVPACK)
355 return false;
118 356
119 *ci->enc_set_header_callback = enc_set_header; 357 memset(&config, 0, sizeof (config));
120 ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality); 358 config.bits_per_sample = PCM_DEPTH_BITS;
359 config.bytes_per_sample = PCM_DEPTH_BYTES;
360 config.sample_rate = inputs.sample_rate;
361 config.num_channels = inputs.num_channels;
362
363 wpc = WavpackOpenFileOutput ();
364
365 if (!WavpackSetConfiguration(wpc, &config, -1))
366 return false;
121 367
122 /* configure the buffer system */ 368 /* configure the buffer system */
123 chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2; 369 params.afmt = AFMT_WAVPACK;
124 num_chunks = enc_buffer_size / chunk_size; 370 input_size = PCM_CHUNK_SIZE*inputs.num_channels / 2;
125 samp_per_chunk = CHUNK_SIZE / 4; 371 data_size = 105*input_size / 100;
372 input_size *= 2;
373 input_step = input_size / 4;
374 params.chunk_size = data_size;
375 params.enc_sample_rate = inputs.sample_rate;
376 params.reserve_bytes = 0;
377 params.events_callback = enc_events_callback;
126 378
127 /* inform the main program about buffer dimensions and other params */ 379 ci->enc_set_parameters(&params);
128 /* add wav_header_mono as place holder to file start position */
129 /* wav header and wvpk header have to be reordered later */
130 ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
131 wav_header_mono, sizeof(wav_header_mono),
132 AFMT_WAVPACK);
133 380
134 wpc = WavpackOpenFileOutput (); 381 return true;
382} /* init_encoder */
383
384enum codec_status codec_start(struct codec_api* api)
385{
386 bool cpu_boosted;
387
388 ci = api; /* copy to global api pointer */
135 389
136 memset (&config, 0, sizeof (config)); 390#ifdef USE_IRAM
137 config.bits_per_sample = 16; 391 ci->memcpy(iramstart, iramcopy, iramend - iramstart);
138 config.bytes_per_sample = 2; 392 ci->memset(iedata, 0, iend - iedata);
139 config.sample_rate = 44100; 393#endif
140 config.num_channels = enc_channels;
141 394
142 if (!WavpackSetConfiguration (wpc, &config, 1)) 395 /* initialize params and config */
396 if (!init_encoder())
397 {
398 ci->enc_codec_loaded = -1;
143 return CODEC_ERROR; 399 return CODEC_ERROR;
400 }
144 401
145 /* main application waits for this flag during encoder loading */ 402 /* main application waits for this flag during encoder loading */
146 ci->enc_codec_loaded = true; 403 ci->enc_codec_loaded = 1;
404
405 ci->cpu_boost(true);
406 cpu_boosted = true;
147 407
148 /* main encoding loop */ 408 /* main encoding loop */
149 while(!ci->stop_codec) 409 while(!ci->stop_codec)
150 { 410 {
151 while((src = (uint32*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL) 411 uint8_t *src;
412
413 while ((src = ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL)
152 { 414 {
415 struct enc_chunk_hdr *chunk;
416 bool abort_chunk;
417 uint8_t *dst;
418 uint8_t *src_end;
419
153 if(ci->stop_codec) 420 if(ci->stop_codec)
154 break; 421 break;
155 422
156 if(ci->enc_wavbuf_near_empty() == 0) 423 abort_chunk = true;
424
425 if (!cpu_boosted && ci->enc_pcm_buf_near_empty() == 0)
157 { 426 {
158 if(!cpu_boosted) 427 ci->cpu_boost(true);
159 { 428 cpu_boosted = true;
160 ci->cpu_boost(true);
161 cpu_boosted = true;
162 }
163 } 429 }
164 430
165 dst = (uint32*)ci->enc_alloc_chunk() + 1; 431 chunk = ci->enc_get_chunk();
166 432
167 WavpackStartBlock (wpc, (uint8*)dst, (uint8*)dst + CHUNK_SIZE); 433 /* reset counts and pointer */
434 chunk->enc_size = 0;
435 chunk->num_pcm = 0;
436 chunk->enc_data = NULL;
168 437
169 if(enc_channels == 2) 438 dst = ENC_CHUNK_SKIP_HDR(dst, chunk);
170 {
171 for (i=0; i<CHUNK_SIZE/4; i++)
172 {
173 t = (long)*src++;
174 439
175 input_buffer[2*i + 0] = t >> 16; 440 WavpackStartBlock(wpc, dst, dst + data_size);
176 input_buffer[2*i + 1] = (short)t; 441
177 } 442 chunk_to_int32((uint32_t*)src);
178 } 443 src = input_buffer;
179 else 444 src_end = src + input_size;
445
446 /* encode chunk in four steps yielding between each */
447 do
180 { 448 {
181 for (i=0; i<CHUNK_SIZE/4; i++) 449 if (WavpackPackSamples(wpc, (int32_t *)src,
450 PCM_SAMP_PER_CHUNK/4))
182 { 451 {
183 t = (long)*src++; 452 chunk->num_pcm += PCM_SAMP_PER_CHUNK/4;
184 t = (((t<<16)>>16) + (t>>16)) >> 1; /* left+right */ 453 ci->yield();
185 454 /* could've been stopped in some way */
186 input_buffer[i] = t; 455 abort_chunk = ci->stop_codec ||
456 (chunk->flags & CHUNKF_ABORT);
187 } 457 }
188 }
189 458
190 if (!WavpackPackSamples (wpc, input_buffer, CHUNK_SIZE/4)) 459 src += input_step;
191 return CODEC_ERROR; 460 }
461 while (!abort_chunk && src < src_end);
192 462
463 if (!abort_chunk)
464 {
465 chunk->enc_data = dst;
466 if (chunk->num_pcm < PCM_SAMP_PER_CHUNK)
467 ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4);
193 /* finish the chunk and store chunk size info */ 468 /* finish the chunk and store chunk size info */
194 dst[-1] = WavpackFinishBlock (wpc); 469 chunk->enc_size = WavpackFinishBlock(wpc);
195 470 ci->enc_finish_chunk();
196 ci->enc_free_chunk(); 471 }
197 ci->yield();
198 } 472 }
199 473
200 if(ci->enc_wavbuf_near_empty()) 474 if (cpu_boosted && ci->enc_pcm_buf_near_empty() != 0)
201 { 475 {
202 if(cpu_boosted) 476 ci->cpu_boost(false);
203 { 477 cpu_boosted = false;
204 ci->cpu_boost(false);
205 cpu_boosted = false;
206 }
207 } 478 }
479
208 ci->yield(); 480 ci->yield();
209 } 481 }
210 482
211 if(cpu_boosted) /* set initial boost state */ 483 if (cpu_boosted) /* set initial boost state */
212 ci->cpu_boost(false); 484 ci->cpu_boost(false);
213 485
214 /* reset parameters to initial state */ 486 /* reset parameters to initial state */
215 ci->enc_set_parameters(0, 0, 0, 0, 0, 0); 487 ci->enc_set_parameters(NULL);
216 488
217 /* main application waits for this flag during encoder removing */ 489 /* main application waits for this flag during encoder removing */
218 ci->enc_codec_loaded = false; 490 ci->enc_codec_loaded = 0;
219 491
220 return CODEC_OK; 492 return CODEC_OK;
221} 493} /* codec_start */
222#endif 494
495#endif /* ndef SIMULATOR */
diff --git a/apps/eq_menu.c b/apps/eq_menu.c
index 6c4dde4a78..9939ee77fe 100644
--- a/apps/eq_menu.c
+++ b/apps/eq_menu.c
@@ -710,7 +710,8 @@ static bool eq_save_preset(void)
710 char filename[MAX_PATH]; 710 char filename[MAX_PATH];
711 int *setting; 711 int *setting;
712 712
713 create_numbered_filename(filename, EQS_DIR, "eq", ".cfg", 2); 713 create_numbered_filename(filename, EQS_DIR, "eq", ".cfg", 2
714 IF_CNFN_NUM_(, NULL));
714 715
715 /* allow user to modify filename */ 716 /* allow user to modify filename */
716 while (true) { 717 while (true) {
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
index a8b8c5061b..ae8bba0538 100644
--- a/apps/gui/statusbar.c
+++ b/apps/gui/statusbar.c
@@ -124,19 +124,6 @@
124#endif 124#endif
125#define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width - 1 - \ 125#define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width - 1 - \
126 STATUSBAR_DISK_WIDTH 126 STATUSBAR_DISK_WIDTH
127#if defined(HAVE_RECORDING)
128/* analogue frequency numbers taken from the order of frequencies in sample_rate */
129#define FREQ_44 7
130#define FREQ_48 8
131#define FREQ_32 6
132#define FREQ_22 4
133#define FREQ_24 5
134#define FREQ_16 3
135#ifdef HAVE_SPDIF_IN
136#define SOURCE_SPDIF 2
137#endif
138#endif
139
140struct gui_syncstatusbar statusbars; 127struct gui_syncstatusbar statusbars;
141 128
142void gui_statusbar_init(struct gui_statusbar * bar) 129void gui_statusbar_init(struct gui_statusbar * bar)
@@ -600,41 +587,113 @@ void gui_statusbar_time(struct screen * display, int hour, int minute)
600#endif 587#endif
601 588
602#ifdef HAVE_RECORDING 589#ifdef HAVE_RECORDING
603void gui_statusbar_icon_recording_info(struct screen * display) 590#if CONFIG_CODEC == SWCODEC
591/**
592 * Write a number to the display using bitmaps and return new position
593 */
594static int write_bitmap_number(struct screen * display, int value,
595 int x, int y)
604{ 596{
605#if (CONFIG_CODEC != SWCODEC) || (defined(SIMULATOR) && defined(HAVE_SPDIF_IN)) 597 char buf[12], *ptr;
606 char buffer[3]; 598 snprintf(buf, sizeof(buf), "%d", value);
599
600 for (ptr = buf; *ptr != '\0'; ptr++, x += BM_GLYPH_WIDTH)
601 display->mono_bitmap(bitmap_glyphs_4x8[*ptr - '0'], x, y,
602 BM_GLYPH_WIDTH, STATUSBAR_HEIGHT);
603 return x;
604}
605
606/**
607 * Write format info bitmaps - right justified
608 */
609static void gui_statusbar_write_format_info(struct screen * display)
610{
611 /* Can't fit info for sw codec targets in statusbar using FONT_SYSFIXED
612 so must use icons */
613 int rec_format = global_settings.rec_format;
614 unsigned bitrk = 0; /* compiler warns about unitialized use !! */
615 int xpos = STATUSBAR_ENCODER_X_POS;
616 int width = STATUSBAR_ENCODER_WIDTH;
617 const unsigned char *bm = bitmap_formats_18x8[rec_format];
618
619 if (rec_format == REC_FORMAT_MPA_L3)
620 {
621 /* Special handling for mp3 */
622 bitrk = global_settings.mp3_enc_config.bitrate;
623 bitrk = mp3_enc_bitr[bitrk];
624
625 width = BM_MPA_L3_M_WIDTH;
626
627 /* Slide 'M' to right if fewer than three digits used */
628 if (bitrk > 999)
629 bitrk = 999; /* neurotic safety check if corrupted */
630 else
631 {
632 if (bitrk < 100)
633 xpos += BM_GLYPH_WIDTH;
634 if (bitrk < 10)
635 xpos += BM_GLYPH_WIDTH;
636 }
637 }
638
639
640 /* Show bitmap - clipping right edge if needed */
641 display->mono_bitmap_part(bm, 0, 0, STATUSBAR_ENCODER_WIDTH,
642 xpos, STATUSBAR_Y_POS, width, STATUSBAR_HEIGHT);
643
644 if (rec_format == REC_FORMAT_MPA_L3)
645 {
646 xpos += BM_MPA_L3_M_WIDTH; /* to right of 'M' */
647 write_bitmap_number(display, bitrk, xpos, STATUSBAR_Y_POS);
648 }
649}
650
651/**
652 * Write sample rate using bitmaps - left justified
653 */
654static void gui_statusbar_write_samplerate_info(struct screen * display)
655{
656 unsigned long samprk;
657 int xpos;
658
659#ifdef SIMULATOR
660 samprk = 44100;
661#else
662#ifdef HAVE_SPDIF_IN
663 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
664 /* Use rate in use, not current measured rate if it changed */
665 samprk = pcm_rec_sample_rate();
666 else
607#endif 667#endif
668 samprk = rec_freq_sampr[global_settings.rec_frequency];
669#endif /* SIMULATOR */
670
671 samprk /= 1000;
672 if (samprk > 99)
673 samprk = 99; /* Limit to 3 glyphs */
674
675 xpos = write_bitmap_number(display, (unsigned)samprk,
676 STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS);
677
678 /* write the 'k' */
679 display->mono_bitmap(bitmap_glyphs_4x8[Glyph_4x8_k], xpos,
680 STATUSBAR_Y_POS, BM_GLYPH_WIDTH,
681 STATUSBAR_HEIGHT);
682}
683#endif /* CONFIG_CODEC == SWCODEC */
684
685void gui_statusbar_icon_recording_info(struct screen * display)
686{
608#if CONFIG_CODEC != SWCODEC 687#if CONFIG_CODEC != SWCODEC
688 char buffer[3];
609 int width, height; 689 int width, height;
610 static char* const sample_rate[12] =
611 {
612 "8",
613 "11",
614 "12",
615 "16",
616 "22",
617 "24",
618 "32",
619 "44",
620 "48",
621 "64",
622 "88",
623 "96"
624 };
625
626 display->setfont(FONT_SYSFIXED); 690 display->setfont(FONT_SYSFIXED);
627#endif 691#endif /* CONFIG_CODEC != SWCODEC */
628 692
629 /* Display Codec info in statusbar */ 693 /* Display Codec info in statusbar */
630#if CONFIG_CODEC == SWCODEC 694#if CONFIG_CODEC == SWCODEC
631 /* Can't fit info for sw codec targets in statusbar using FONT_SYSFIXED 695 gui_statusbar_write_format_info(display);
632 so must use icons */ 696#else /* !SWCODEC */
633 display->mono_bitmap(bitmap_icons_18x8[global_settings.rec_quality],
634 STATUSBAR_ENCODER_X_POS, STATUSBAR_Y_POS,
635 STATUSBAR_ENCODER_WIDTH, STATUSBAR_HEIGHT);
636#else
637
638 display->mono_bitmap(bitmap_icons_5x8[Icon_q], 697 display->mono_bitmap(bitmap_icons_5x8[Icon_q],
639 STATUSBAR_ENCODER_X_POS + 8, STATUSBAR_Y_POS, 698 STATUSBAR_ENCODER_X_POS + 8, STATUSBAR_Y_POS,
640 5, STATUSBAR_HEIGHT); 699 5, STATUSBAR_HEIGHT);
@@ -643,56 +702,37 @@ void gui_statusbar_icon_recording_info(struct screen * display)
643 display->getstringsize(buffer, &width, &height); 702 display->getstringsize(buffer, &width, &height);
644 if (height <= STATUSBAR_HEIGHT) 703 if (height <= STATUSBAR_HEIGHT)
645 display->putsxy(STATUSBAR_ENCODER_X_POS + 13, STATUSBAR_Y_POS, buffer); 704 display->putsxy(STATUSBAR_ENCODER_X_POS + 13, STATUSBAR_Y_POS, buffer);
646#endif 705#endif /* CONFIG_CODEC == SWCODEC */
647 706
648 /* Display Samplerate info in statusbar */ 707 /* Display Samplerate info in statusbar */
649#if defined(HAVE_SPDIF_IN) 708#if CONFIG_CODEC == SWCODEC
650 if (global_settings.rec_source == SOURCE_SPDIF) 709 /* SWCODEC targets use bitmaps for glyphs */
710 gui_statusbar_write_samplerate_info(display);
711#else /* !SWCODEC */
712 /* hwcodec targets have sysfont characters */
713#ifdef HAVE_SPDIF_IN
714 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
651 { 715 {
652#if (CONFIG_CODEC != MAS3587F) && !defined(SIMULATOR)
653 display->mono_bitmap(bitmap_icons_12x8[audio_get_spdif_sample_rate()],
654 STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS,
655 STATUSBAR_RECFREQ_WIDTH, STATUSBAR_HEIGHT);
656#else
657 /* Can't measure S/PDIF sample rate on Archos/Sim yet */ 716 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
658 snprintf(buffer, sizeof(buffer), "--"); 717 snprintf(buffer, sizeof(buffer), "--");
659#endif
660 } 718 }
661 else 719 else
662#endif /* HAVE_SPDIF_IN */ 720#endif /* HAVE_SPDIF_IN */
663 { 721 {
664 /* Analogue frequency in wrong order so remap settings numbers */ 722 static char const * const freq_strings[12] =
665 int freq = global_settings.rec_frequency; 723 { "44", "48", "32", "22", "24", "16" };
666 if (freq == 0) 724 snprintf(buffer, sizeof(buffer), "%s",
667 freq = FREQ_44; 725 freq_strings[global_settings.rec_frequency]);
668 else if (freq == 1)
669 freq = FREQ_48;
670 else if (freq == 2)
671 freq = FREQ_32;
672 else if (freq == 3)
673 freq = FREQ_22;
674 else if (freq == 4)
675 freq = FREQ_24;
676 else if (freq == 5)
677 freq = FREQ_16;
678
679#if CONFIG_CODEC == SWCODEC
680 /* samplerate icons for swcodec targets*/
681 display->mono_bitmap(bitmap_icons_12x8[freq],
682 STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS,
683 STATUSBAR_RECFREQ_WIDTH, STATUSBAR_HEIGHT);
684 }
685#else
686 /* hwcodec targets have sysfont characters */
687 snprintf(buffer, sizeof(buffer), "%s", sample_rate[freq]);
688 display->getstringsize(buffer, &width, &height);
689 } 726 }
690 727
691 if (height <= STATUSBAR_HEIGHT) 728 display->getstringsize(buffer, &width, &height);
692 display->putsxy(STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS, buffer); 729
730 if (height <= STATUSBAR_HEIGHT)
731 display->putsxy(STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS, buffer);
732
733 display->setfont(FONT_UI);
734#endif /* CONFIG_CODEC == SWCODEC */
693 735
694 display->setfont(FONT_UI);
695#endif
696 /* Display Channel status in status bar */ 736 /* Display Channel status in status bar */
697 if(global_settings.rec_channels) 737 if(global_settings.rec_channels)
698 { 738 {
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 40d7bb7b19..8f7deb78a9 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -9802,7 +9802,7 @@
9802</phrase> 9802</phrase>
9803<phrase> 9803<phrase>
9804 id: VOICE_KBIT_PER_SEC 9804 id: VOICE_KBIT_PER_SEC
9805 desc: spoken only, for file extension 9805 desc: spoken only, a unit postfix
9806 user: 9806 user:
9807 <source> 9807 <source>
9808 *: "" 9808 *: ""
@@ -10032,3 +10032,115 @@
10032 *: "" 10032 *: ""
10033 </voice> 10033 </voice>
10034</phrase> 10034</phrase>
10035<phrase>
10036 id: LANG_RECORDING_FORMAT
10037 desc: audio format item in recording menu
10038 user:
10039 <source>
10040 *: "Format"
10041 </source>
10042 <dest>
10043 *: "Format"
10044 </dest>
10045 <voice>
10046 *: "Format"
10047 </voice>
10048</phrase>
10049<phrase>
10050 id: LANG_AFMT_MPA_L3
10051 desc: audio format description
10052 user:
10053 <source>
10054 *: "MPEG Layer 3"
10055 </source>
10056 <dest>
10057 *: "MPEG Layer 3"
10058 </dest>
10059 <voice>
10060 *: "MPEG Layer 3"
10061 </voice>
10062</phrase>
10063<phrase>
10064 id: LANG_AFMT_PCM_WAV
10065 desc: audio format description
10066 user:
10067 <source>
10068 *: "PCM Wave"
10069 </source>
10070 <dest>
10071 *: "PCM Wave"
10072 </dest>
10073 <voice>
10074 *: "PCM Wave"
10075 </voice>
10076</phrase>
10077<phrase>
10078 id: LANG_AFMT_WAVPACK
10079 desc: audio format description
10080 user:
10081 <source>
10082 *: "WavPack"
10083 </source>
10084 <dest>
10085 *: "WavPack"
10086 </dest>
10087 <voice>
10088 *: "WavPack"
10089 </voice>
10090</phrase>
10091<phrase>
10092 id: LANG_ENCODER_SETTINGS
10093 desc: encoder settings
10094 user:
10095 <source>
10096 *: "Encoder Settings"
10097 </source>
10098 <dest>
10099 *: "Encoder Settings"
10100 </dest>
10101 <voice>
10102 *: "Encoder Settings"
10103 </voice>
10104</phrase>
10105<phrase>
10106 id: LANG_NO_SETTINGS
10107 desc: when something has settings in a certain context
10108 user:
10109 <source>
10110 *: "(No Settings)"
10111 </source>
10112 <dest>
10113 *: "(No Settings)"
10114 </dest>
10115 <voice>
10116 *: "No settings available"
10117 </voice>
10118</phrase>
10119<phrase>
10120 id: LANG_SOURCE_FREQUENCY
10121 desc: when recording source frequency setting must follow source
10122 user:
10123 <source>
10124 *: "(Same As Source)"
10125 </source>
10126 <dest>
10127 *: "(Same As Source)"
10128 </dest>
10129 <voice>
10130 *: "Same As Source"
10131 </voice>
10132</phrase>
10133<phrase>
10134 id: LANG_BITRATE
10135 desc: bits-kilobits per unit time
10136 user:
10137 <source>
10138 *: "Bitrate"
10139 </source>
10140 <dest>
10141 *: "Bitrate"
10142 </dest>
10143 <voice>
10144 *: "Bitrate"
10145 </voice>
10146</phrase>
diff --git a/apps/main.c b/apps/main.c
index c4ee45cb89..05b4ab54a3 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -286,6 +286,9 @@ void init(void)
286 286
287#ifdef HAVE_ADJUSTABLE_CPU_FREQ 287#ifdef HAVE_ADJUSTABLE_CPU_FREQ
288 set_cpu_frequency(CPUFREQ_NORMAL); 288 set_cpu_frequency(CPUFREQ_NORMAL);
289#ifdef CPU_COLDFIRE
290 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
291#endif
289 cpu_boost_id(true, CPUBOOSTID_MAININIT); 292 cpu_boost_id(true, CPUBOOSTID_MAININIT);
290#endif 293#endif
291 294
diff --git a/apps/metadata.c b/apps/metadata.c
index ee0100ecf7..845536877c 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -88,36 +88,6 @@ struct apetag_item_header
88 long flags; 88 long flags;
89}; 89};
90 90
91struct format_list
92{
93 char format;
94 char extension[5];
95};
96
97static const struct format_list formats[] =
98{
99 { AFMT_MPA_L1, "mp1" },
100 { AFMT_MPA_L2, "mp2" },
101 { AFMT_MPA_L2, "mpa" },
102 { AFMT_MPA_L3, "mp3" },
103#if CONFIG_CODEC == SWCODEC
104 { AFMT_OGG_VORBIS, "ogg" },
105 { AFMT_PCM_WAV, "wav" },
106 { AFMT_FLAC, "flac" },
107 { AFMT_MPC, "mpc" },
108 { AFMT_A52, "a52" },
109 { AFMT_A52, "ac3" },
110 { AFMT_WAVPACK, "wv" },
111 { AFMT_ALAC, "m4a" },
112 { AFMT_AAC, "mp4" },
113 { AFMT_SHN, "shn" },
114 { AFMT_AIFF, "aif" },
115 { AFMT_AIFF, "aiff" },
116 { AFMT_SID, "sid" },
117 { AFMT_ADX, "adx" },
118#endif
119};
120
121#if CONFIG_CODEC == SWCODEC 91#if CONFIG_CODEC == SWCODEC
122static const unsigned short a52_bitrates[] = 92static const unsigned short a52_bitrates[] =
123{ 93{
@@ -1691,14 +1661,24 @@ unsigned int probe_file_format(const char *filename)
1691 return AFMT_UNKNOWN; 1661 return AFMT_UNKNOWN;
1692 } 1662 }
1693 1663
1694 suffix += 1; 1664 /* skip '.' */
1665 suffix++;
1666
1667 for (i = 1; i < AFMT_NUM_CODECS; i++)
1668 {
1669 /* search extension list for type */
1670 const char *ext = audio_formats[i].ext_list;
1695 1671
1696 for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) 1672 do
1697 { 1673 {
1698 if (strcasecmp(suffix, formats[i].extension) == 0) 1674 if (strcasecmp(suffix, ext) == 0)
1699 { 1675 {
1700 return formats[i].format; 1676 return i;
1677 }
1678
1679 ext += strlen(ext) + 1;
1701 } 1680 }
1681 while (*ext != '\0');
1702 } 1682 }
1703 1683
1704 return AFMT_UNKNOWN; 1684 return AFMT_UNKNOWN;
diff --git a/apps/misc.c b/apps/misc.c
index c36d61914b..01463851be 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -58,6 +58,8 @@
58#endif /* End HAVE_LCD_BITMAP */ 58#endif /* End HAVE_LCD_BITMAP */
59#include "gui/gwps-common.h" 59#include "gui/gwps-common.h"
60 60
61#include "misc.h"
62
61/* Format a large-range value for output, using the appropriate unit so that 63/* Format a large-range value for output, using the appropriate unit so that
62 * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" 64 * the displayed value is in the range 1 <= display < 1000 (1024 for "binary"
63 * units) if possible, and 3 significant digits are shown. If a buffer is 65 * units) if possible, and 3 significant digits are shown. If a buffer is
@@ -114,16 +116,20 @@ char *output_dyn_value(char *buf, int buf_size, int value,
114} 116}
115 117
116/* Create a filename with a number part in a way that the number is 1 118/* Create a filename with a number part in a way that the number is 1
117 higher than the highest numbered file matching the same pattern. 119 * higher than the highest numbered file matching the same pattern.
118 It is allowed that buffer and path point to the same memory location, 120 * It is allowed that buffer and path point to the same memory location,
119 saving a strcpy(). Path must always be given without trailing slash,. */ 121 * saving a strcpy(). Path must always be given without trailing slash.
122 * "num" can point to an int specifying the number to use or NULL or a value
123 * less than zero to number automatically. The final number used will also
124 * be returned in *num. If *num is >= 0 then *num will be incremented by
125 * one. */
120char *create_numbered_filename(char *buffer, const char *path, 126char *create_numbered_filename(char *buffer, const char *path,
121 const char *prefix, const char *suffix, 127 const char *prefix, const char *suffix,
122 int numberlen) 128 int numberlen IF_CNFN_NUM_(, int *num))
123{ 129{
124 DIR *dir; 130 DIR *dir;
125 struct dirent *entry; 131 struct dirent *entry;
126 int max_num = 0; 132 int max_num;
127 int pathlen; 133 int pathlen;
128 int prefixlen = strlen(prefix); 134 int prefixlen = strlen(prefix);
129 char fmtstring[12]; 135 char fmtstring[12];
@@ -133,6 +139,18 @@ char *create_numbered_filename(char *buffer, const char *path,
133 139
134 pathlen = strlen(buffer); 140 pathlen = strlen(buffer);
135 141
142#ifdef IF_CNFN_NUM
143 if (num && *num >= 0)
144 {
145 /* number specified */
146 max_num = *num;
147 }
148 else
149#endif
150 {
151 /* automatic numbering */
152 max_num = 0;
153
136 dir = opendir(pathlen ? buffer : "/"); 154 dir = opendir(pathlen ? buffer : "/");
137 if (!dir) 155 if (!dir)
138 return NULL; 156 return NULL;
@@ -149,11 +167,20 @@ char *create_numbered_filename(char *buffer, const char *path,
149 if (curr_num > max_num) 167 if (curr_num > max_num)
150 max_num = curr_num; 168 max_num = curr_num;
151 } 169 }
170
152 closedir(dir); 171 closedir(dir);
172 }
173
174 max_num++;
153 175
154 snprintf(fmtstring, sizeof(fmtstring), "/%%s%%0%dd%%s", numberlen); 176 snprintf(fmtstring, sizeof(fmtstring), "/%%s%%0%dd%%s", numberlen);
155 snprintf(buffer + pathlen, MAX_PATH - pathlen, fmtstring, prefix, 177 snprintf(buffer + pathlen, MAX_PATH - pathlen, fmtstring, prefix,
156 max_num + 1, suffix); 178 max_num, suffix);
179
180#ifdef IF_CNFN_NUM
181 if (num)
182 *num = max_num;
183#endif
157 184
158 return buffer; 185 return buffer;
159} 186}
@@ -161,13 +188,22 @@ char *create_numbered_filename(char *buffer, const char *path,
161#ifdef CONFIG_RTC 188#ifdef CONFIG_RTC
162/* Create a filename with a date+time part. 189/* Create a filename with a date+time part.
163 It is allowed that buffer and path point to the same memory location, 190 It is allowed that buffer and path point to the same memory location,
164 saving a strcpy(). Path must always be given without trailing slash. */ 191 saving a strcpy(). Path must always be given without trailing slash.
192 unique_time as true makes the function wait until the current time has
193 changed. */
165char *create_datetime_filename(char *buffer, const char *path, 194char *create_datetime_filename(char *buffer, const char *path,
166 const char *prefix, const char *suffix) 195 const char *prefix, const char *suffix,
196 bool unique_time)
167{ 197{
168 struct tm *tm = get_time(); 198 struct tm *tm = get_time();
199 static struct tm last_tm;
169 int pathlen; 200 int pathlen;
170 201
202 while (unique_time && !memcmp(get_time(), &last_tm, sizeof (struct tm)))
203 sleep(HZ/10);
204
205 last_tm = *tm;
206
171 if (buffer != path) 207 if (buffer != path)
172 strncpy(buffer, path, MAX_PATH); 208 strncpy(buffer, path, MAX_PATH);
173 209
@@ -356,9 +392,10 @@ void screen_dump(void)
356#endif 392#endif
357 393
358#ifdef CONFIG_RTC 394#ifdef CONFIG_RTC
359 create_datetime_filename(filename, "", "dump ", ".bmp"); 395 create_datetime_filename(filename, "", "dump ", ".bmp", false);
360#else 396#else
361 create_numbered_filename(filename, "", "dump_", ".bmp", 4); 397 create_numbered_filename(filename, "", "dump_", ".bmp", 4
398 IF_CNFN_NUM_(, NULL));
362#endif 399#endif
363 400
364 fh = creat(filename, O_WRONLY); 401 fh = creat(filename, O_WRONLY);
diff --git a/apps/misc.h b/apps/misc.h
index 1bc9a23447..6c660e0a5e 100644
--- a/apps/misc.h
+++ b/apps/misc.h
@@ -19,21 +19,46 @@
19#ifndef MISC_H 19#ifndef MISC_H
20#define MISC_H 20#define MISC_H
21 21
22#include <stdbool.h>
23
22/* Format a large-range value for output, using the appropriate unit so that 24/* Format a large-range value for output, using the appropriate unit so that
23 * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" 25 * the displayed value is in the range 1 <= display < 1000 (1024 for "binary"
24 * units) if possible, and 3 significant digits are shown. If a buffer is 26 * units) if possible, and 3 significant digits are shown. If a buffer is
25 * given, the result is snprintf()'d into that buffer, otherwise the result is 27 * given, the result is snprintf()'d into that buffer, otherwise the result is
26 * voiced.*/ 28 * voiced.*/
27void output_dyn_value(char *buf, int buf_size, int value, 29char *output_dyn_value(char *buf, int buf_size, int value,
28 const unsigned char **units, bool bin_scale); 30 const unsigned char **units, bool bin_scale);
29 31
32/* Create a filename with a number part in a way that the number is 1
33 * higher than the highest numbered file matching the same pattern.
34 * It is allowed that buffer and path point to the same memory location,
35 * saving a strcpy(). Path must always be given without trailing slash.
36 *
37 * "num" can point to an int specifying the number to use or NULL or a value
38 * less than zero to number automatically. The final number used will also
39 * be returned in *num. If *num is >= 0 then *num will be incremented by
40 * one. */
41#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) && !defined(CONFIG_RTC)
42/* this feature is needed by SWCODEC recording without a RTC to prevent
43 disk access when changing files */
44#define IF_CNFN_NUM_(...) __VA_ARGS__
45#define IF_CNFN_NUM
46#else
47#define IF_CNFN_NUM_(...)
48#endif
30char *create_numbered_filename(char *buffer, const char *path, 49char *create_numbered_filename(char *buffer, const char *path,
31 const char *prefix, const char *suffix, 50 const char *prefix, const char *suffix,
32 int numberlen); 51 int numberlen IF_CNFN_NUM_(, int *num));
33#ifdef CONFIG_RTC 52#ifdef CONFIG_RTC
53/* Create a filename with a date+time part.
54 It is allowed that buffer and path point to the same memory location,
55 saving a strcpy(). Path must always be given without trailing slash.
56 unique_time as true makes the function wait until the current time has
57 changed. */
34char *create_datetime_filename(char *buffer, const char *path, 58char *create_datetime_filename(char *buffer, const char *path,
35 const char *prefix, const char *suffix); 59 const char *prefix, const char *suffix,
36#endif 60 bool unique_time);
61#endif /* CONFIG_RTC */
37 62
38/* Read (up to) a line of text from fd into buffer and return number of bytes 63/* Read (up to) a line of text from fd into buffer and return number of bytes
39 * read (which may be larger than the number of bytes stored in buffer). If 64 * read (which may be larger than the number of bytes stored in buffer). If
@@ -57,4 +82,4 @@ long default_event_handler(long event);
57void car_adapter_mode_init(void); 82void car_adapter_mode_init(void);
58extern int show_logo(void); 83extern int show_logo(void);
59 84
60#endif 85#endif /* MISC_H */
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index 44f175c67d..5119d20ebd 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -51,9 +51,11 @@ struct pcmbufdesc
51 void (*callback)(void); 51 void (*callback)(void);
52}; 52};
53 53
54#define PCMBUF_DESCS(bufsize) ((bufsize) / PCMBUF_MINAVG_CHUNK)
55
54/* Size of the PCM buffer. */ 56/* Size of the PCM buffer. */
55static size_t pcmbuf_size IDATA_ATTR = 0; 57static size_t pcmbuf_size IDATA_ATTR = 0;
56 58static char *pcmbuf_bufend IDATA_ATTR;
57static char *audiobuffer IDATA_ATTR; 59static char *audiobuffer IDATA_ATTR;
58/* Current audio buffer write index. */ 60/* Current audio buffer write index. */
59static size_t audiobuffer_pos IDATA_ATTR; 61static size_t audiobuffer_pos IDATA_ATTR;
@@ -360,7 +362,7 @@ int pcmbuf_used_descs(void) {
360} 362}
361 363
362int pcmbuf_descs(void) { 364int pcmbuf_descs(void) {
363 return pcmbuf_size / PCMBUF_MINAVG_CHUNK; 365 return PCMBUF_DESCS(pcmbuf_size);
364} 366}
365 367
366size_t get_pcmbuf_descsize(void) { 368size_t get_pcmbuf_descsize(void) {
@@ -371,28 +373,37 @@ static void pcmbuf_init_pcmbuffers(void) {
371 struct pcmbufdesc *next = pcmbuf_write; 373 struct pcmbufdesc *next = pcmbuf_write;
372 next++; 374 next++;
373 pcmbuf_write_end = pcmbuf_write; 375 pcmbuf_write_end = pcmbuf_write;
374 while ((void *)next < (void *)audiobufend) { 376 while ((void *)next < (void *)pcmbuf_bufend) {
375 pcmbuf_write_end->link=next; 377 pcmbuf_write_end->link=next;
376 pcmbuf_write_end=next; 378 pcmbuf_write_end=next;
377 next++; 379 next++;
378 } 380 }
379} 381}
380 382
383bool pcmbuf_is_same_size(size_t bufsize)
384{
385 /* keep calculations synced with pcmbuf_init */
386 bufsize += PCMBUF_MIX_CHUNK * 2 + PCMBUF_DESCS(bufsize);
387 return bufsize == (size_t)(pcmbuf_bufend - audiobuffer);
388}
389
381/* Initialize the pcmbuffer the structure looks like this: 390/* Initialize the pcmbuffer the structure looks like this:
382 * ...CODECBUFFER|---------PCMBUF---------|GUARDBUF|DESCS| */ 391 * ...|---------PCMBUF---------|FADEBUF|VOICEBUF|DESCS|... */
383void pcmbuf_init(size_t bufsize) 392size_t pcmbuf_init(size_t bufsize, char *bufend)
384{ 393{
385 pcmbuf_size = bufsize; 394 pcmbuf_size = bufsize;
395 pcmbuf_bufend = bufend;
386 pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc); 396 pcmbuf_descsize = pcmbuf_descs()*sizeof(struct pcmbufdesc);
387 audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) - 397 audiobuffer = pcmbuf_bufend - (pcmbuf_size + PCMBUF_MIX_CHUNK * 2
388 (pcmbuf_size + PCMBUF_MIX_CHUNK * 2 + pcmbuf_descsize)]; 398 + pcmbuf_descsize);
389 fadebuf = &audiobuffer[pcmbuf_size]; 399 fadebuf = &audiobuffer[pcmbuf_size];
390 voicebuf = &fadebuf[PCMBUF_MIX_CHUNK]; 400 voicebuf = &fadebuf[PCMBUF_MIX_CHUNK];
391 pcmbuf_write = (struct pcmbufdesc *)(&voicebuf[PCMBUF_MIX_CHUNK]); 401 pcmbuf_write = (struct pcmbufdesc *)&voicebuf[PCMBUF_MIX_CHUNK];
392 pcmbuf_init_pcmbuffers(); 402 pcmbuf_init_pcmbuffers();
393 position_callback = NULL; 403 position_callback = NULL;
394 pcmbuf_event_handler = NULL; 404 pcmbuf_event_handler = NULL;
395 pcmbuf_play_stop(); 405 pcmbuf_play_stop();
406 return pcmbuf_bufend - audiobuffer;
396} 407}
397 408
398size_t pcmbuf_get_bufsize(void) 409size_t pcmbuf_get_bufsize(void)
diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h
index b5035f4405..a408cdae42 100644
--- a/apps/pcmbuf.h
+++ b/apps/pcmbuf.h
@@ -38,7 +38,7 @@
38 38
39/* Returns true if the buffer needs to change size */ 39/* Returns true if the buffer needs to change size */
40bool pcmbuf_is_same_size(size_t bufsize); 40bool pcmbuf_is_same_size(size_t bufsize);
41void pcmbuf_init(size_t bufsize); 41size_t pcmbuf_init(size_t bufsize, char *bufend);
42/* Size in bytes used by the pcmbuffer */ 42/* Size in bytes used by the pcmbuffer */
43size_t pcmbuf_get_bufsize(void); 43size_t pcmbuf_get_bufsize(void);
44size_t get_pcmbuf_descsize(void); 44size_t get_pcmbuf_descsize(void);
diff --git a/apps/playback.c b/apps/playback.c
index f8372665a4..af6b573f1d 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -54,8 +54,6 @@
54#include "playlist.h" 54#include "playlist.h"
55#include "playback.h" 55#include "playback.h"
56#include "pcmbuf.h" 56#include "pcmbuf.h"
57#include "pcm_playback.h"
58#include "pcm_record.h"
59#include "buffer.h" 57#include "buffer.h"
60#include "dsp.h" 58#include "dsp.h"
61#include "abrepeat.h" 59#include "abrepeat.h"
@@ -78,6 +76,7 @@
78 76
79#ifdef HAVE_RECORDING 77#ifdef HAVE_RECORDING
80#include "recording.h" 78#include "recording.h"
79#include "talk.h"
81#endif 80#endif
82 81
83#define PLAYBACK_VOICE 82#define PLAYBACK_VOICE
@@ -93,9 +92,13 @@
93 * for their correct seeek target, 32k seems a good size */ 92 * for their correct seeek target, 32k seems a good size */
94#define AUDIO_REBUFFER_GUESS_SIZE (1024*32) 93#define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
95 94
96/* macros to enable logf for queues */ 95/* macros to enable logf for queues
96 logging on SYS_TIMEOUT can be disabled */
97#ifdef SIMULATOR 97#ifdef SIMULATOR
98#define PLAYBACK_LOGQUEUES /* Define this for logf output of all queuing */ 98/* Define this for logf output of all queuing except SYS_TIMEOUT */
99#define PLAYBACK_LOGQUEUES
100/* Define this to logf SYS_TIMEOUT messages */
101#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT
99#endif 102#endif
100 103
101#ifdef PLAYBACK_LOGQUEUES 104#ifdef PLAYBACK_LOGQUEUES
@@ -104,6 +107,18 @@
104#define LOGFQUEUE(s) 107#define LOGFQUEUE(s)
105#endif 108#endif
106 109
110#ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
111#define LOGFQUEUE_SYS_TIMEOUT(s) logf("%s", s)
112#else
113#define LOGFQUEUE_SYS_TIMEOUT(s)
114#endif
115
116
117/* Define one constant that includes recording related functionality */
118#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
119#define AUDIO_HAVE_RECORDING
120#endif
121
107enum { 122enum {
108 Q_AUDIO_PLAY = 1, 123 Q_AUDIO_PLAY = 1,
109 Q_AUDIO_STOP, 124 Q_AUDIO_STOP,
@@ -122,6 +137,9 @@ enum {
122#if MEM > 8 137#if MEM > 8
123 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 138 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
124#endif 139#endif
140#ifdef AUDIO_HAVE_RECORDING
141 Q_AUDIO_LOAD_ENCODER,
142#endif
125 143
126 Q_CODEC_REQUEST_PENDING, 144 Q_CODEC_REQUEST_PENDING,
127 Q_CODEC_REQUEST_COMPLETE, 145 Q_CODEC_REQUEST_COMPLETE,
@@ -133,7 +151,7 @@ enum {
133 Q_CODEC_LOAD, 151 Q_CODEC_LOAD,
134 Q_CODEC_LOAD_DISK, 152 Q_CODEC_LOAD_DISK,
135 153
136#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 154#ifdef AUDIO_HAVE_RECORDING
137 Q_ENCODER_LOAD_DISK, 155 Q_ENCODER_LOAD_DISK,
138 Q_ENCODER_RECORD, 156 Q_ENCODER_RECORD,
139#endif 157#endif
@@ -178,11 +196,16 @@ static volatile bool paused; /* Is audio paused? (A/C-) */
178static volatile bool filling IDATA_ATTR; /* Is file buffer currently being refilled? (A/C-) */ 196static volatile bool filling IDATA_ATTR; /* Is file buffer currently being refilled? (A/C-) */
179 197
180/* Ring buffer where tracks and codecs are loaded */ 198/* Ring buffer where tracks and codecs are loaded */
181static char *filebuf; /* Pointer to start of ring buffer (A/C-) */ 199static unsigned char *filebuf; /* Pointer to start of ring buffer (A/C-) */
182size_t filebuflen; /* Total size of the ring buffer FIXME: make static (A/C-)*/ 200size_t filebuflen; /* Total size of the ring buffer FIXME: make static (A/C-)*/
183static volatile size_t buf_ridx IDATA_ATTR; /* Ring buffer read position (A/C) FIXME? should be (C/A-) */ 201static volatile size_t buf_ridx IDATA_ATTR; /* Ring buffer read position (A/C) FIXME? should be (C/A-) */
184static volatile size_t buf_widx IDATA_ATTR; /* Ring buffer read position (A/C-) */ 202static volatile size_t buf_widx IDATA_ATTR; /* Ring buffer read position (A/C-) */
185 203
204#define BUFFER_STATE_TRASHED -1 /* Buffer is in a trashed state and must be reset */
205#define BUFFER_STATE_NORMAL 0 /* Buffer is arranged for voice and audio */
206#define BUFFER_STATE_VOICED_ONLY 1 /* Buffer is arranged for voice-only use */
207static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
208
186#define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen) 209#define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
187#define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v) 210#define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
188#define RINGBUF_ADD_CROSS(p1,v,p2) ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen) 211#define RINGBUF_ADD_CROSS(p1,v,p2) ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen)
@@ -235,7 +258,7 @@ static const char audio_thread_name[] = "audio";
235static void audio_thread(void); 258static void audio_thread(void);
236static void audio_initiate_track_change(long direction); 259static void audio_initiate_track_change(long direction);
237static bool audio_have_tracks(void); 260static bool audio_have_tracks(void);
238static void audio_reset_buffer(void); 261static void audio_reset_buffer(size_t pcmbufsize);
239 262
240/* Codec thread */ 263/* Codec thread */
241extern struct codec_api ci; 264extern struct codec_api ci;
@@ -294,6 +317,10 @@ static void voice_thread(void);
294void mp3_play_data(const unsigned char* start, int size, 317void mp3_play_data(const unsigned char* start, int size,
295 void (*get_more)(unsigned char** start, int* size)) 318 void (*get_more)(unsigned char** start, int* size))
296{ 319{
320 /* must reset the buffer before any playback begins if needed */
321 if (buffer_state == BUFFER_STATE_TRASHED)
322 audio_reset_buffer(pcmbuf_get_bufsize());
323
297#ifdef PLAYBACK_VOICE 324#ifdef PLAYBACK_VOICE
298 static struct voice_info voice_clip; 325 static struct voice_info voice_clip;
299 voice_clip.callback = get_more; 326 voice_clip.callback = get_more;
@@ -330,38 +357,95 @@ void mpeg_id3_options(bool _v1first)
330 v1first = _v1first; 357 v1first = _v1first;
331} 358}
332 359
333void audio_load_encoder(int enc_id) 360unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
334{ 361{
335#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 362 unsigned char *buf = audiobuf;
336 const char *enc_fn = get_codec_filename(enc_id | CODEC_TYPE_ENCODER); 363 unsigned char *end = audiobufend;
364
365 audio_stop();
366
367 if (talk_buf || !talk_voice_required()
368 || buffer_state == BUFFER_STATE_TRASHED)
369 {
370 logf("get buffer: talk_buf");
371 /* ok to use everything from audiobuf to audiobufend */
372 if (buffer_state != BUFFER_STATE_TRASHED)
373 talk_buffer_steal();
374 buffer_state = BUFFER_STATE_TRASHED;
375 }
376 else
377 {
378 /* skip talk buffer and move pcm buffer to end */
379 logf("get buffer: voice");
380 mp3_play_stop();
381 buf += talk_get_bufsize();
382 end -= pcmbuf_init(pcmbuf_get_bufsize(), audiobufend);
383 buffer_state = BUFFER_STATE_VOICED_ONLY;
384 }
385
386 *buffer_size = end - buf;
387
388 return buf;
389}
390
391#ifdef HAVE_RECORDING
392unsigned char *audio_get_recording_buffer(size_t *buffer_size)
393{
394 /* don't allow overwrite of voice swap area or we'll trash the
395 swapped-out voice codec but can use whole thing if none */
396 unsigned char *end = iram_buf[CODEC_IDX_VOICE] ?
397 iram_buf[CODEC_IDX_VOICE] : audiobufend;
398
399 audio_stop();
400 talk_buffer_steal();
401
402 buffer_state = BUFFER_STATE_TRASHED;
403
404 *buffer_size = end - audiobuf;
405
406 return (unsigned char *)audiobuf;
407}
408
409bool audio_load_encoder(int afmt)
410{
411#ifndef SIMULATOR
412 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
337 if (!enc_fn) 413 if (!enc_fn)
338 return; 414 return false;
339 415
340 audio_remove_encoder(); 416 audio_remove_encoder();
417 ci.enc_codec_loaded = 0; /* clear any previous error condition */
341 418
342 LOGFQUEUE("audio > codec Q_ENCODER_LOAD_DISK"); 419 LOGFQUEUE("audio > Q_AUDIO_LOAD_ENCODER");
343 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (void *)enc_fn); 420 queue_post(&audio_queue, Q_AUDIO_LOAD_ENCODER, (void *)enc_fn);
344 421
345 while (!ci.enc_codec_loaded) 422 while (ci.enc_codec_loaded == 0)
346 yield(); 423 yield();
424
425 logf("codec loaded: %d", ci.enc_codec_loaded);
426
427 return ci.enc_codec_loaded > 0;
428#else
429 (void)afmt;
430 return true;
347#endif 431#endif
348 return;
349 (void)enc_id;
350} /* audio_load_encoder */ 432} /* audio_load_encoder */
351 433
352void audio_remove_encoder(void) 434void audio_remove_encoder(void)
353{ 435{
354#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 436#ifndef SIMULATOR
355 /* force encoder codec unload (if previously loaded) */ 437 /* force encoder codec unload (if currently loaded) */
356 if (!ci.enc_codec_loaded) 438 if (ci.enc_codec_loaded <= 0)
357 return; 439 return;
358 440
359 ci.stop_codec = true; 441 ci.stop_codec = true;
360 while (ci.enc_codec_loaded) 442 while (ci.enc_codec_loaded > 0)
361 yield(); 443 yield();
362#endif 444#endif
363} /* audio_remove_encoder */ 445} /* audio_remove_encoder */
364 446
447#endif /* HAVE_RECORDING */
448
365struct mp3entry* audio_current_track(void) 449struct mp3entry* audio_current_track(void)
366{ 450{
367 const char *filename; 451 const char *filename;
@@ -553,6 +637,9 @@ void audio_flush_and_reload_tracks(void)
553 637
554void audio_error_clear(void) 638void audio_error_clear(void)
555{ 639{
640#ifdef AUDIO_HAVE_RECORDING
641 pcm_rec_error_clear();
642#endif
556} 643}
557 644
558int audio_status(void) 645int audio_status(void)
@@ -573,11 +660,6 @@ int audio_status(void)
573 return ret; 660 return ret;
574} 661}
575 662
576bool audio_query_poweroff(void)
577{
578 return !(playing && paused);
579}
580
581int audio_get_file_pos(void) 663int audio_get_file_pos(void)
582{ 664{
583 return 0; 665 return 0;
@@ -617,7 +699,7 @@ void audio_set_crossfade(int enable)
617 enable = 0; 699 enable = 0;
618 size = NATIVE_FREQUENCY*2; 700 size = NATIVE_FREQUENCY*2;
619#endif 701#endif
620 if (pcmbuf_get_bufsize() == size) 702 if (buffer_state == BUFFER_STATE_NORMAL && pcmbuf_is_same_size(size))
621 return ; 703 return ;
622 704
623 if (was_playing) 705 if (was_playing)
@@ -633,9 +715,8 @@ void audio_set_crossfade(int enable)
633 voice_stop(); 715 voice_stop();
634 716
635 /* Re-initialize audio system. */ 717 /* Re-initialize audio system. */
636 pcmbuf_init(size); 718 audio_reset_buffer(size);
637 pcmbuf_crossfade_enable(enable); 719 pcmbuf_crossfade_enable(enable);
638 audio_reset_buffer();
639 logf("abuf:%dB", pcmbuf_get_bufsize()); 720 logf("abuf:%dB", pcmbuf_get_bufsize());
640 logf("fbuf:%dB", filebuflen); 721 logf("fbuf:%dB", filebuflen);
641 722
@@ -714,8 +795,7 @@ void voice_stop(void)
714{ 795{
715#ifdef PLAYBACK_VOICE 796#ifdef PLAYBACK_VOICE
716 /* Messages should not be posted to voice codec queue unless it is the 797 /* Messages should not be posted to voice codec queue unless it is the
717 current codec or deadlocks happen. 798 current codec or deadlocks happen. */
718 -- jhMikeS */
719 if (current_codec != CODEC_IDX_VOICE) 799 if (current_codec != CODEC_IDX_VOICE)
720 return; 800 return;
721 801
@@ -784,21 +864,32 @@ static void set_filebuf_watermark(int seconds)
784 conf_watermark = bytes; 864 conf_watermark = bytes;
785} 865}
786 866
787static const char * get_codec_filename(int enc_spec) 867static const char * get_codec_filename(int cod_spec)
788{ 868{
789 const char *fname; 869 const char *fname;
790 int type = enc_spec & CODEC_TYPE_MASK; 870
791 int afmt = enc_spec & CODEC_AFMT_MASK; 871#ifdef HAVE_RECORDING
872 /* Can choose decoder or encoder if one available */
873 int type = cod_spec & CODEC_TYPE_MASK;
874 int afmt = cod_spec & CODEC_AFMT_MASK;
792 875
793 if ((unsigned)afmt >= AFMT_NUM_CODECS) 876 if ((unsigned)afmt >= AFMT_NUM_CODECS)
794 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK); 877 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
795 878
796 fname = (type == CODEC_TYPE_DECODER) ? 879 fname = (type == CODEC_TYPE_ENCODER) ?
797 audio_formats[afmt].codec_fn : audio_formats[afmt].codec_enc_fn; 880 audio_formats[afmt].codec_enc_root_fn :
881 audio_formats[afmt].codec_root_fn;
798 882
799 logf("%s: %d - %s", 883 logf("%s: %d - %s",
800 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder", 884 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
801 afmt, fname ? fname : "<unknown>"); 885 afmt, fname ? fname : "<unknown>");
886#else /* !HAVE_RECORDING */
887 /* Always decoder */
888 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
889 cod_spec = AFMT_UNKNOWN;
890 fname = audio_formats[cod_spec].codec_root_fn;
891 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
892#endif /* HAVE_RECORDING */
802 893
803 return fname; 894 return fname;
804} /* get_codec_filename */ 895} /* get_codec_filename */
@@ -940,7 +1031,7 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
940 } 1031 }
941 break; 1032 break;
942 1033
943#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 1034#ifdef AUDIO_HAVE_RECORDING
944 case Q_ENCODER_RECORD: 1035 case Q_ENCODER_RECORD:
945 LOGFQUEUE("voice < Q_ENCODER_RECORD"); 1036 LOGFQUEUE("voice < Q_ENCODER_RECORD");
946 swap_codec(); 1037 swap_codec();
@@ -995,7 +1086,7 @@ static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
995 goto voice_play_clip; 1086 goto voice_play_clip;
996 1087
997 case SYS_TIMEOUT: 1088 case SYS_TIMEOUT:
998 LOGFQUEUE("voice < SYS_TIMEOUT"); 1089 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
999 goto voice_play_clip; 1090 goto voice_play_clip;
1000 1091
1001 default: 1092 default:
@@ -1773,7 +1864,7 @@ static void codec_thread(void)
1773#endif 1864#endif
1774 break ; 1865 break ;
1775 1866
1776#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 1867#ifdef AUDIO_HAVE_RECORDING
1777 case Q_ENCODER_LOAD_DISK: 1868 case Q_ENCODER_LOAD_DISK:
1778 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK"); 1869 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1779 audio_codec_loaded = false; /* Not audio codec! */ 1870 audio_codec_loaded = false; /* Not audio codec! */
@@ -1785,12 +1876,14 @@ static void codec_thread(void)
1785 } 1876 }
1786#endif 1877#endif
1787 mutex_lock(&mutex_codecthread); 1878 mutex_lock(&mutex_codecthread);
1879 logf("loading encoder");
1788 current_codec = CODEC_IDX_AUDIO; 1880 current_codec = CODEC_IDX_AUDIO;
1789 ci.stop_codec = false; 1881 ci.stop_codec = false;
1790 status = codec_load_file((const char *)ev.data, &ci); 1882 status = codec_load_file((const char *)ev.data, &ci);
1791 mutex_unlock(&mutex_codecthread); 1883 mutex_unlock(&mutex_codecthread);
1884 logf("encoder stopped");
1792 break; 1885 break;
1793#endif 1886#endif /* AUDIO_HAVE_RECORDING */
1794 1887
1795#ifndef SIMULATOR 1888#ifndef SIMULATOR
1796 case SYS_USB_CONNECTED: 1889 case SYS_USB_CONNECTED:
@@ -1872,6 +1965,24 @@ static void codec_thread(void)
1872 } 1965 }
1873 break; 1966 break;
1874 1967
1968#ifdef AUDIO_HAVE_RECORDING
1969 case Q_ENCODER_LOAD_DISK:
1970 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1971
1972 if (status == CODEC_OK)
1973 break;
1974
1975 logf("Encoder failure");
1976 gui_syncsplash(HZ*2, true, "Encoder failure");
1977
1978 if (ci.enc_codec_loaded < 0)
1979 break;
1980
1981 logf("Encoder failed to load");
1982 ci.enc_codec_loaded = -1;
1983 break;
1984#endif /* AUDIO_HAVE_RECORDING */
1985
1875 default: 1986 default:
1876 LOGFQUEUE("codec < default"); 1987 LOGFQUEUE("codec < default");
1877 1988
@@ -2992,6 +3103,10 @@ static void audio_play_start(size_t offset)
2992 /* Wait for any previously playing audio to flush - TODO: Not necessary? */ 3103 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
2993 audio_stop_codec_flush(); 3104 audio_stop_codec_flush();
2994 3105
3106 /* must reset the buffer before any playback begins if needed */
3107 if (buffer_state != BUFFER_STATE_NORMAL)
3108 audio_reset_buffer(pcmbuf_get_bufsize());
3109
2995 track_changed = true; 3110 track_changed = true;
2996 playlist_end = false; 3111 playlist_end = false;
2997 3112
@@ -3084,51 +3199,60 @@ static void audio_initiate_dir_change(long direction)
3084 ci.new_track = direction; 3199 ci.new_track = direction;
3085} 3200}
3086 3201
3087static void audio_reset_buffer(void) 3202/*
3203 * Layout audio buffer as follows:
3204 * [|TALK]|MALLOC|FILE|GUARD|PCM|AUDIOCODEC|[VOICECODEC|]
3205 */
3206static void audio_reset_buffer(size_t pcmbufsize)
3088{ 3207{
3208 /* see audio_get_recording_buffer if this is modified */
3089 size_t offset; 3209 size_t offset;
3090 3210
3091 /* Set up file buffer as all space available */ 3211 logf("audio_reset_buffer");
3092 filebuf = (char *)&audiobuf[talk_get_bufsize()+MALLOC_BUFSIZE]; 3212 logf(" size:%08X", pcmbufsize);
3093 filebuflen = audiobufend - (unsigned char *) filebuf - GUARD_BUFSIZE - 3213
3094 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_MIX_CHUNK * 2); 3214 /* Initially set up file buffer as all space available */
3215 filebuf = audiobuf + MALLOC_BUFSIZE + talk_get_bufsize();
3216 filebuflen = audiobufend - filebuf;
3095 3217
3096 /* Allow for codec(s) at end of file buffer */ 3218 /* Allow for codec(s) at end of audio buffer */
3097 if (talk_voice_required()) 3219 if (talk_voice_required())
3098 { 3220 {
3099 /* Allow 2 codecs at end of file buffer */ 3221#ifdef PLAYBACK_VOICE
3222 /* Allow 2 codecs at end of audio buffer */
3100 filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE); 3223 filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE);
3101 3224
3102#ifdef PLAYBACK_VOICE 3225 iram_buf[CODEC_IDX_AUDIO] = filebuf + filebuflen;
3103 iram_buf[0] = &filebuf[filebuflen]; 3226 dram_buf[CODEC_IDX_AUDIO] = iram_buf[CODEC_IDX_AUDIO] + CODEC_IRAM_SIZE;
3104 iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE]; 3227 iram_buf[CODEC_IDX_VOICE] = dram_buf[CODEC_IDX_AUDIO] + CODEC_SIZE;
3105 dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2]; 3228 dram_buf[CODEC_IDX_VOICE] = iram_buf[CODEC_IDX_VOICE] + CODEC_IRAM_SIZE;
3106 dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE];
3107#endif 3229#endif
3108 } 3230 }
3109 else 3231 else
3110 { 3232 {
3111 /* Allow for 1 codec at end of file buffer */ 3233#ifdef PLAYBACK_VOICE
3234 /* Allow for 1 codec at end of audio buffer */
3112 filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE; 3235 filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE;
3113 3236
3114#ifdef PLAYBACK_VOICE 3237 iram_buf[CODEC_IDX_AUDIO] = filebuf + filebuflen;
3115 iram_buf[0] = &filebuf[filebuflen]; 3238 dram_buf[CODEC_IDX_AUDIO] = iram_buf[CODEC_IDX_AUDIO] + CODEC_IRAM_SIZE;
3116 iram_buf[1] = NULL; 3239 iram_buf[CODEC_IDX_VOICE] = NULL;
3117 dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE]; 3240 dram_buf[CODEC_IDX_VOICE] = NULL;
3118 dram_buf[1] = NULL;
3119#endif 3241#endif
3120 } 3242 }
3121 3243
3244 filebuflen -= pcmbuf_init(pcmbufsize, filebuf + filebuflen) + GUARD_BUFSIZE;
3245
3122 /* Ensure that file buffer is aligned */ 3246 /* Ensure that file buffer is aligned */
3123 offset = (-(size_t)filebuf) & 3; 3247 offset = -(size_t)filebuf & 3;
3124 filebuf += offset; 3248 filebuf += offset;
3125 filebuflen -= offset; 3249 filebuflen -= offset;
3126 filebuflen &= ~3; 3250 filebuflen &= ~3;
3127 3251
3128 /* Clear any references to the file buffer */ 3252 /* Clear any references to the file buffer */
3253 buffer_state = BUFFER_STATE_NORMAL;
3129} 3254}
3130 3255
3131
3132#ifdef ROCKBOX_HAS_LOGF 3256#ifdef ROCKBOX_HAS_LOGF
3133static void audio_test_track_changed_event(struct mp3entry *id3) 3257static void audio_test_track_changed_event(struct mp3entry *id3)
3134{ 3258{
@@ -3149,9 +3273,8 @@ static void audio_playback_init(void)
3149 logf("playback api init"); 3273 logf("playback api init");
3150 pcm_init(); 3274 pcm_init();
3151 3275
3152#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 3276#ifdef AUDIO_HAVE_RECORDING
3153 /* Set the input multiplexer to Line In */ 3277 rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3154 pcm_rec_mux(0);
3155#endif 3278#endif
3156 3279
3157#ifdef ROCKBOX_HAS_LOGF 3280#ifdef ROCKBOX_HAS_LOGF
@@ -3219,8 +3342,9 @@ static void audio_playback_init(void)
3219#endif 3342#endif
3220 } 3343 }
3221 3344
3222 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; /* Will be reset by reset_buffer */ 3345 /* initialize the buffer */
3223 3346 filebuf = audiobuf; /* must be non-NULL for audio_set_crossfade */
3347 buffer_state = BUFFER_STATE_TRASHED; /* force it */
3224 audio_set_crossfade(global_settings.crossfade); 3348 audio_set_crossfade(global_settings.crossfade);
3225 3349
3226 audio_is_initialized = true; 3350 audio_is_initialized = true;
@@ -3358,6 +3482,14 @@ static void audio_thread(void)
3358 playlist_update_resume_info(audio_current_track()); 3482 playlist_update_resume_info(audio_current_track());
3359 break ; 3483 break ;
3360 3484
3485#ifdef AUDIO_HAVE_RECORDING
3486 case Q_AUDIO_LOAD_ENCODER:
3487 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER");
3488 LOGFQUEUE("audio > codec Q_ENCODER_LOAD_DISK");
3489 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, ev.data);
3490 break;
3491#endif
3492
3361#ifndef SIMULATOR 3493#ifndef SIMULATOR
3362 case SYS_USB_CONNECTED: 3494 case SYS_USB_CONNECTED:
3363 LOGFQUEUE("audio < SYS_USB_CONNECTED"); 3495 LOGFQUEUE("audio < SYS_USB_CONNECTED");
@@ -3368,7 +3500,7 @@ static void audio_thread(void)
3368#endif 3500#endif
3369 3501
3370 case SYS_TIMEOUT: 3502 case SYS_TIMEOUT:
3371 LOGFQUEUE("audio < SYS_TIMEOUT"); 3503 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3372 break; 3504 break;
3373 3505
3374 default: 3506 default:
diff --git a/apps/playlist.c b/apps/playlist.c
index 5a5313b736..134b52ea8b 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -155,7 +155,7 @@ static int recreate_control(struct playlist_info* playlist);
155static void update_playlist_filename(struct playlist_info* playlist, 155static void update_playlist_filename(struct playlist_info* playlist,
156 const char *dir, const char *file); 156 const char *dir, const char *file);
157static int add_indices_to_playlist(struct playlist_info* playlist, 157static int add_indices_to_playlist(struct playlist_info* playlist,
158 char* buffer, int buflen); 158 char* buffer, size_t buflen);
159static int add_track_to_playlist(struct playlist_info* playlist, 159static int add_track_to_playlist(struct playlist_info* playlist,
160 const char *filename, int position, 160 const char *filename, int position,
161 bool queue, int seek_pos); 161 bool queue, int seek_pos);
@@ -457,7 +457,7 @@ static void update_playlist_filename(struct playlist_info* playlist,
457 * calculate track offsets within a playlist file 457 * calculate track offsets within a playlist file
458 */ 458 */
459static int add_indices_to_playlist(struct playlist_info* playlist, 459static int add_indices_to_playlist(struct playlist_info* playlist,
460 char* buffer, int buflen) 460 char* buffer, size_t buflen)
461{ 461{
462 unsigned int nread; 462 unsigned int nread;
463 unsigned int i = 0; 463 unsigned int i = 0;
@@ -489,8 +489,7 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
489 buflen = (audiobufend - audiobuf); 489 buflen = (audiobufend - audiobuf);
490 buffer = (char *)audiobuf; 490 buffer = (char *)audiobuf;
491#else 491#else
492 buflen = (audiobufend - audiobuf - talk_get_bufsize()); 492 buffer = (char *)audio_get_buffer(false, &buflen);
493 buffer = (char *)&audiobuf[talk_get_bufsize()];
494#endif 493#endif
495 } 494 }
496 495
@@ -1853,7 +1852,7 @@ int playlist_resume(void)
1853{ 1852{
1854 struct playlist_info* playlist = &current_playlist; 1853 struct playlist_info* playlist = &current_playlist;
1855 char *buffer; 1854 char *buffer;
1856 int buflen; 1855 size_t buflen;
1857 int nread; 1856 int nread;
1858 int total_read = 0; 1857 int total_read = 0;
1859 int control_file_size = 0; 1858 int control_file_size = 0;
@@ -1866,8 +1865,7 @@ int playlist_resume(void)
1866 buflen = (audiobufend - audiobuf); 1865 buflen = (audiobufend - audiobuf);
1867 buffer = (char *)audiobuf; 1866 buffer = (char *)audiobuf;
1868#else 1867#else
1869 buflen = (audiobufend - audiobuf - talk_get_bufsize()); 1868 buffer = (char *)audio_get_buffer(false, &buflen);
1870 buffer = (char *)&audiobuf[talk_get_bufsize()];
1871#endif 1869#endif
1872 1870
1873 empty_playlist(playlist, true); 1871 empty_playlist(playlist, true);
diff --git a/apps/plugin.c b/apps/plugin.c
index 25f1865c9e..3a893fc537 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -674,12 +674,18 @@ void* plugin_get_buffer(int* buffer_size)
674} 674}
675 675
676/* Returns a pointer to the mp3 buffer. 676/* Returns a pointer to the mp3 buffer.
677 Playback gets stopped, to avoid conflicts. */ 677 Playback gets stopped, to avoid conflicts.
678 Talk buffer is stolen as well.
679 */
678void* plugin_get_audio_buffer(int* buffer_size) 680void* plugin_get_audio_buffer(int* buffer_size)
679{ 681{
682#if CONFIG_CODEC == SWCODEC
683 return audio_get_buffer(true, (size_t *)buffer_size);
684#else
680 audio_stop(); 685 audio_stop();
681 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ 686 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
682 *buffer_size = audiobufend - audiobuf; 687 *buffer_size = audiobufend - audiobuf;
688#endif
683 return audiobuf; 689 return audiobuf;
684} 690}
685 691
diff --git a/apps/recorder/icons.c b/apps/recorder/icons.c
index 46d628e780..ba22bb5a2c 100644
--- a/apps/recorder/icons.c
+++ b/apps/recorder/icons.c
@@ -30,12 +30,17 @@
30 30
31const unsigned char bitmap_icons_5x8[][5] = 31const unsigned char bitmap_icons_5x8[][5] =
32{ 32{
33 [Icon_Lock_Main] ={0x78,0x7f,0x49,0x7f,0x78}, /* Lock Main */ 33 [Icon_Lock_Main] =
34 [Icon_Lock_Remote]={0x78,0x7f,0x49,0x7f,0x78}, /* Lock Remote */ 34 {0x78, 0x7f, 0x49, 0x7f, 0x78}, /* Lock Main */
35 [Icon_Stereo]={0x7f, 0x1c, 0x00, 0x1c, 0x7f}, /* Stereo recording */ 35 [Icon_Lock_Remote] =
36 [Icon_Mono]={0x00, 0x1c, 0x7f, 0x00, 0x00}, /* Mono recording */ 36 {0x78, 0x7f, 0x49, 0x7f, 0x78}, /* Lock Remote */
37 [Icon_Stereo] =
38 {0x7f, 0x22, 0x1c, 0x22, 0x7f}, /* Stereo recording */
39 [Icon_Mono] =
40 {0x00, 0x1c, 0x22, 0x7f, 0x00}, /* Mono recording */
37#if CONFIG_CODEC != SWCODEC 41#if CONFIG_CODEC != SWCODEC
38 [Icon_q]={0x1e, 0x21, 0x31, 0x21, 0x5e} /* Q icon */ 42 [Icon_q] =
43 {0x1e, 0x21, 0x31, 0x21, 0x5e} /* Q icon */
39#endif 44#endif
40}; 45};
41 46
@@ -81,45 +86,52 @@ const unsigned char bitmap_icons_7x8[][7] =
81 {0x7f,0x04,0x4e,0x5f,0x44,0x38,0x7f} /* Repeat-AB playmode */ 86 {0x7f,0x04,0x4e,0x5f,0x44,0x38,0x7f} /* Repeat-AB playmode */
82}; 87};
83 88
84#if CONFIG_CODEC == SWCODEC 89#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING)
85const unsigned char bitmap_icons_18x8[][18] = 90const unsigned char bitmap_glyphs_4x8[][4] =
86{ 91{
87 {0x00, 0x00, 0x00, 0x00,0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x3e, 0x2a, 92 /* Keep digits together and first! */
88 0x3a, 0x00, 0x0e, 0x08, 0x3e, 0x00}, /* mp3 64kbps */ 93 [0] =
89 {0x00, 0x00, 0x00, 0x00,0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x0e, 0x0a, 94 {0x00, 0x3e, 0x22, 0x3e}, /* 0 */
90 0x3e, 0x00, 0x3e, 0x2a, 0x3a, 0x00}, /* mp3 96kbps */ 95 [1] =
91 {0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x24, 0x3e, 0x20, 0x00, 0x3a, 0x2a, 96 {0x00, 0x24, 0x3e, 0x20}, /* 1 */
92 0x2e, 0x00, 0x3e, 0x2a, 0x3e, 0x00}, /* mp3 128kbps */ 97 [2] =
93 {0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x24, 0x3e, 0x20, 0x00, 0x3e, 0x2a, 98 {0x00, 0x3a, 0x2a, 0x2e}, /* 2 */
94 0x3a, 0x00, 0x3e, 0x22, 0x3e, 0x00}, /* mp3 160kbps */ 99 [3] =
95 {0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x24, 0x3e, 0x20, 0x00, 0x0e, 0x0a, 100 {0x00, 0x22, 0x2a, 0x36}, /* 3 */
96 0x3e, 0x00, 0x3a, 0x2a, 0x2e, 0x00}, /* mp3 192kbps */ 101 [4] =
97 {0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x3a, 0x2a, 0x2e, 0x00, 0x3a, 0x2a, 102 {0x00, 0x0e, 0x08, 0x3e}, /* 4 */
98 0x2e, 0x00, 0x0e, 0x08, 0x3e, 0x00}, /* mp3 224kbps */ 103 [5] =
99 {0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x22, 0x2a, 0x36, 0x00, 0x3a, 0x2a, 104 {0x00, 0x2e, 0x2a, 0x3a}, /* 5 */
100 0x2e, 0x00, 0x3e, 0x22, 0x3e, 0x00}, /* mp3 320kbps */ 105 [6] =
101 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x1e, 0x20, 0x18, 0x20, 0x1e, 106 {0x00, 0x3e, 0x2a, 0x3a}, /* 6 */
102 0x00, 0x1e, 0x20, 0x18, 0x06, 0x00}, /* wv */ 107 [7] =
103 {0x00, 0x00, 0x1e, 0x20, 0x18, 0x20, 0x1e, 0x00, 0x3c, 0x12, 0x12, 0x3c, 108 {0x00, 0x02, 0x02, 0x3e}, /* 7 */
104 0x00, 0x1e, 0x20, 0x18, 0x06, 0x00} /* wav */ 109 [8] =
110 {0x00, 0x3e, 0x2a, 0x3e}, /* 8 */
111 [9] =
112 {0x00, 0x0e, 0x0a, 0x3e}, /* 9 */
113 [10 ... Glyph_4x8Last-1] =
114 {0x00, 0x00, 0x00, 0x00}, /* auto-blank */
115 [Glyph_4x8_k] =
116 {0x00, 0x3e, 0x10, 0x28}, /* k */
105}; 117};
106 118
107const unsigned char bitmap_icons_12x8[][12] = 119const unsigned char bitmap_formats_18x8[Format_18x8Last][18]=
108{ 120{
109 {0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x2a, 0x3e, 0x00, 0x3e, 0x10, 0x28}, /* 8khz */ 121 [0 ... Format_18x8Last-1] = /* auto-blank */
110 {0x00, 0x24, 0x3e, 0x20, 0x00, 0x24, 0x3e, 0x20, 0x00, 0x3e, 0x10, 0x28}, /* 11khz */ 122 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 {0x00, 0x24, 0x3e, 0x20, 0x00, 0x3a, 0x2a, 0x2e, 0x00, 0x3e, 0x10, 0x28}, /* 12khz */ 123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* ___ */
112 {0x00, 0x24, 0x3e, 0x20, 0x00, 0x3e, 0x2a, 0x3a, 0x00, 0x3e, 0x10, 0x28}, /* 16khz */ 124 [Format_18x8_MPA_L3] =
113 {0x00, 0x3a, 0x2a, 0x2e, 0x00, 0x3a, 0x2a, 0x2e, 0x00, 0x3e, 0x10, 0x28}, /* 22khz */ 125 {0x00, 0x3e, 0x04, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00,
114 {0x00, 0x3a, 0x2a, 0x2e, 0x00, 0x0e, 0x08, 0x3e, 0x00, 0x3e, 0x10, 0x28}, /* 24khz */ 126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* M__ */
115 {0x00, 0x22, 0x2a, 0x36, 0x00, 0x3a, 0x2a, 0x2e, 0x00, 0x3e, 0x10, 0x28}, /* 32khz */ 127 [Format_18x8_WAVPACK] =
116 {0x00, 0x0e, 0x08, 0x3e, 0x00, 0x0e, 0x08, 0x3e, 0x00, 0x3e, 0x10, 0x28}, /* 44.1khz */ 128 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20,
117 {0x00, 0x0e, 0x08, 0x3e, 0x00, 0x3e, 0x2a, 0x3e, 0x00, 0x3e, 0x10, 0x28}, /* 48khz */ 129 0x18, 0x20, 0x1e, 0x00, 0x0e, 0x10, 0x20, 0x10, 0x0e}, /* _WV */
118 {0x00, 0x3e, 0x2a, 0x3a, 0x00, 0x0e, 0x08, 0x3e, 0x00, 0x3e, 0x10, 0x28}, /* 64khz */ 130 [Format_18x8_PCM_WAV] =
119 {0x00, 0x3e, 0x2a, 0x3e, 0x00, 0x3e, 0x2a, 0x3e, 0x00, 0x3e, 0x10, 0x28}, /* 88.2khz */ 131 {0x00, 0x1e, 0x20, 0x18, 0x20, 0x1e, 0x00, 0x3c, 0x0a,
120 {0x00, 0x0e, 0x0a, 0x3e, 0x00, 0x3e, 0x2a, 0x3a, 0x00, 0x3e, 0x10, 0x28} /* 96khz */ 132 0x0a, 0x0a, 0x3c, 0x00, 0x0e, 0x10, 0x20, 0x10, 0x0e}, /* WAV */
121}; 133};
122#endif 134#endif /* CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) */
123 135
124/* Disk/MMC activity */ 136/* Disk/MMC activity */
125const unsigned char bitmap_icon_disk[12] = 137const unsigned char bitmap_icon_disk[12] =
diff --git a/apps/recorder/icons.h b/apps/recorder/icons.h
index 75401f6f0b..1e7b8dba1e 100644
--- a/apps/recorder/icons.h
+++ b/apps/recorder/icons.h
@@ -89,44 +89,40 @@ enum icons_7x8 {
89 Icon7x8Last 89 Icon7x8Last
90}; 90};
91 91
92#if CONFIG_CODEC == SWCODEC 92#if CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING)
93enum icons_12x8 { 93#define BM_GLYPH_WIDTH 4
94 Icon_8000, 94enum Glyphs_4x8 {
95 Icon_11025, 95 Glyph_4x8_0 = 0,
96 Icon_12000, 96 Glyph_4x8_1,
97 Icon_16000, 97 Glyph_4x8_2,
98 Icon_22050, 98 Glyph_4x8_3,
99 Icon_24000, 99 Glyph_4x8_4,
100 Icon_32000, 100 Glyph_4x8_5,
101 Icon_44100, 101 Glyph_4x8_6,
102 Icon_48000, 102 Glyph_4x8_7,
103 Icon_64000, 103 Glyph_4x8_8,
104 Icon_88200, 104 Glyph_4x8_9,
105 Icon_96000, 105 Glyph_4x8_k,
106 Icon12x8Last 106 Glyph_4x8Last
107}; 107};
108 108extern const unsigned char bitmap_glyphs_4x8[Glyph_4x8Last][4];
109enum icons_18x8 { 109
110 Icon_mp364, 110#define BM_MPA_L3_M_WIDTH 6
111 Icon_mp396, 111#ifdef ID3_H
112 Icon_mp3128, 112/* This enum is redundant but sort of in keeping with the style */
113 Icon_mp3160, 113enum rec_format_18x8 {
114 Icon_mp3192, 114 Format_18x8_MPA_L3 = REC_FORMAT_MPA_L3,
115 Icon_mp3224, 115 Format_18x8_WAVPACK = REC_FORMAT_WAVPACK,
116 Icon_mp3320, 116 Format_18x8_PCM_WAV = REC_FORMAT_PCM_WAV,
117 Icon_wv, 117 Format_18x8Last = REC_NUM_FORMATS
118 Icon_wav,
119 Icon18x8Last
120}; 118};
121#endif 119extern const unsigned char bitmap_formats_18x8[Format_18x8Last][18];
120#endif /* ID3_H */
121#endif /* CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING) */
122 122
123extern const unsigned char bitmap_icons_5x8[Icon5x8Last][5]; 123extern const unsigned char bitmap_icons_5x8[Icon5x8Last][5];
124extern const unsigned char bitmap_icons_6x8[Icon6x8Last][6]; 124extern const unsigned char bitmap_icons_6x8[Icon6x8Last][6];
125extern const unsigned char bitmap_icons_7x8[Icon7x8Last][7]; 125extern const unsigned char bitmap_icons_7x8[Icon7x8Last][7];
126#if CONFIG_CODEC == SWCODEC
127extern const unsigned char bitmap_icons_12x8[Icon12x8Last][12];
128extern const unsigned char bitmap_icons_18x8[Icon18x8Last][18];
129#endif
130extern const unsigned char bitmap_icon_disk[]; 126extern const unsigned char bitmap_icon_disk[];
131 127
132#define STATUSBAR_X_POS 0 128#define STATUSBAR_X_POS 0
diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c
index 0370f4deea..44be43124a 100644
--- a/apps/recorder/peakmeter.c
+++ b/apps/recorder/peakmeter.c
@@ -540,10 +540,8 @@ void peak_meter_peek(void)
540 if (pm_playback) 540 if (pm_playback)
541 pcm_calculate_peaks(&pm_cur_left, &pm_cur_right); 541 pcm_calculate_peaks(&pm_cur_left, &pm_cur_right);
542#ifdef HAVE_RECORDING 542#ifdef HAVE_RECORDING
543 if (!pm_playback) 543 else
544 { 544 pcm_calculate_rec_peaks(&pm_cur_left, &pm_cur_right);
545 pcm_rec_get_peaks(&pm_cur_left, &pm_cur_right);
546 }
547#endif 545#endif
548 left = pm_cur_left; 546 left = pm_cur_left;
549 right = pm_cur_right; 547 right = pm_cur_right;
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c
index d74437a8c9..7a0cc6543e 100644
--- a/apps/recorder/radio.c
+++ b/apps/recorder/radio.c
@@ -386,6 +386,7 @@ bool radio_screen(void)
386 unsigned int last_seconds = 0; 386 unsigned int last_seconds = 0;
387#if CONFIG_CODEC != SWCODEC 387#if CONFIG_CODEC != SWCODEC
388 int hours, minutes; 388 int hours, minutes;
389 struct audio_recording_options rec_options;
389#endif 390#endif
390 bool keep_playing = false; 391 bool keep_playing = false;
391 bool statusbar = global_settings.statusbar; 392 bool statusbar = global_settings.statusbar;
@@ -436,12 +437,9 @@ bool radio_screen(void)
436 437
437 peak_meter_enabled = true; 438 peak_meter_enabled = true;
438 439
439 rec_set_recording_options(global_settings.rec_frequency, 440 rec_init_recording_options(&rec_options);
440 global_settings.rec_quality, 441 rec_options.rec_source = AUDIO_SRC_LINEIN;
441 AUDIO_SRC_LINEIN, 0, 442 rec_set_recording_options(&rec_options);
442 global_settings.rec_channels,
443 global_settings.rec_editable,
444 global_settings.rec_prerecord_time);
445 443
446 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), 444 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
447 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); 445 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
@@ -881,7 +879,7 @@ bool radio_screen(void)
881 } 879 }
882 else 880 else
883 { 881 {
884 if(global_settings.rec_prerecord_time) 882 if(rec_options.rec_prerecord_time)
885 { 883 {
886 snprintf(buf, 32, "%s %02d", 884 snprintf(buf, 32, "%s %02d",
887 str(LANG_RECORD_PRERECORD), seconds%60); 885 str(LANG_RECORD_PRERECORD), seconds%60);
@@ -1173,7 +1171,8 @@ bool save_preset_list(void)
1173 if(!opendir(FMPRESET_PATH)) /* Check if there is preset folder */ 1171 if(!opendir(FMPRESET_PATH)) /* Check if there is preset folder */
1174 mkdir(FMPRESET_PATH, 0); 1172 mkdir(FMPRESET_PATH, 0);
1175 1173
1176 create_numbered_filename(filepreset,FMPRESET_PATH,"preset",".fmr",2); 1174 create_numbered_filename(filepreset, FMPRESET_PATH, "preset",
1175 ".fmr", 2 IF_CNFN_NUM_(, NULL));
1177 1176
1178 while(bad_file_name) 1177 while(bad_file_name)
1179 { 1178 {
@@ -1534,12 +1533,10 @@ static bool fm_recording_settings(void)
1534#if CONFIG_CODEC != SWCODEC 1533#if CONFIG_CODEC != SWCODEC
1535 if (!ret) 1534 if (!ret)
1536 { 1535 {
1537 rec_set_recording_options(global_settings.rec_frequency, 1536 struct audio_recording_options rec_options;
1538 global_settings.rec_quality, 1537 rec_init_recording_options(&rec_options);
1539 AUDIO_SRC_LINEIN, 0, 1538 rec_options.rec_source = AUDIO_SRC_LINEIN;
1540 global_settings.rec_channels, 1539 rec_set_recording_options(&rec_options);
1541 global_settings.rec_editable,
1542 global_settings.rec_prerecord_time);
1543 } 1540 }
1544#endif 1541#endif
1545 1542
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 0a21d96566..6a053cd12e 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -30,8 +30,10 @@
30#include "mpeg.h" 30#include "mpeg.h"
31#include "audio.h" 31#include "audio.h"
32#if CONFIG_CODEC == SWCODEC 32#if CONFIG_CODEC == SWCODEC
33#include "pcm_record.h" 33#include "thread.h"
34#include "pcm_playback.h"
34#include "playback.h" 35#include "playback.h"
36#include "enc_config.h"
35#endif 37#endif
36#ifdef HAVE_UDA1380 38#ifdef HAVE_UDA1380
37#include "uda1380.h" 39#include "uda1380.h"
@@ -73,36 +75,40 @@
73 75
74#define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1) 76#define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1)
75 77
78#if CONFIG_KEYPAD == RECORDER_PAD
76bool f2_rec_screen(void); 79bool f2_rec_screen(void);
77bool f3_rec_screen(void); 80bool f3_rec_screen(void);
81#endif
78 82
79#define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */ 83#define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */
80 84
81int screen_update = NB_SCREENS; 85int screen_update = NB_SCREENS;
82bool remote_display_on = true; 86bool remote_display_on = true;
83const char* const freq_str[6] =
84{
85 "44.1kHz",
86 "48kHz",
87 "32kHz",
88 "22.05kHz",
89 "24kHz",
90 "16kHz"
91};
92 87
88/** File name creation **/
93#if CONFIG_CODEC == SWCODEC 89#if CONFIG_CODEC == SWCODEC
94#define REC_ENCODER_ID(q) \ 90
95 rec_quality_info_afmt[q] 91#ifdef IF_CNFN_NUM
96#define REC_QUALITY_LABEL(q) \ 92/* current file number to assist in creating unique numbered filenames
97 (audio_formats[REC_ENCODER_ID(q)].label) 93 without actually having to create the file on disk */
98#define REC_FILE_ENDING(q) \ 94static int file_number = -1;
99 (audio_formats[REC_ENCODER_ID(q)].ext) 95#endif /* IF_CNFN_NUM */
100#else 96
97#define REC_FILE_ENDING(rec_format) \
98 (audio_formats[rec_format_afmt[rec_format]].ext_list)
99
100#else /* CONFIG_CODEC != SWCODEC */
101
101/* default record file extension for HWCODEC */ 102/* default record file extension for HWCODEC */
102#define REC_QUALITY_LABEL(q) "MP3" 103#define REC_FILE_ENDING(rec_format) \
103#define REC_FILE_ENDING(q) ".mp3" 104 (audio_formats[AFMT_MPA_L3].ext_list)
104#endif
105 105
106#endif /* CONFIG_CODEC == SWCODEC */
107
108/* path for current file */
109static char path_buffer[MAX_PATH];
110
111/** Automatic Gain Control (AGC) **/
106#ifdef HAVE_AGC 112#ifdef HAVE_AGC
107/* Timing counters: 113/* Timing counters:
108 * peak_time is incremented every 0.2s, every 2nd run of record screen loop. 114 * peak_time is incremented every 0.2s, every 2nd run of record screen loop.
@@ -496,20 +502,24 @@ void adjust_cursor(void)
496 502
497char *rec_create_filename(char *buffer) 503char *rec_create_filename(char *buffer)
498{ 504{
505 char ext[16];
506
499 if(global_settings.rec_directory) 507 if(global_settings.rec_directory)
500 getcwd(buffer, MAX_PATH); 508 getcwd(buffer, MAX_PATH);
501 else 509 else
502 strncpy(buffer, rec_base_directory, MAX_PATH); 510 strncpy(buffer, rec_base_directory, MAX_PATH);
503 511
512 snprintf(ext, sizeof(ext), ".%s",
513 REC_FILE_ENDING(global_settings.rec_format));
504 514
505#ifdef CONFIG_RTC 515#ifdef CONFIG_RTC
506 create_datetime_filename(buffer, buffer, "R", 516 /* We'll wait at least up to the start of the next second so no duplicate
507 REC_FILE_ENDING(global_settings.rec_quality)); 517 names are created */
518 return create_datetime_filename(buffer, buffer, "R", ext, true);
508#else 519#else
509 create_numbered_filename(buffer, buffer, "rec_", 520 return create_numbered_filename(buffer, buffer, "rec_", ext, 4
510 REC_FILE_ENDING(global_settings.rec_quality), 4); 521 IF_CNFN_NUM_(, &file_number));
511#endif 522#endif
512 return buffer;
513} 523}
514 524
515int rec_create_directory(void) 525int rec_create_directory(void)
@@ -557,9 +567,15 @@ static void rec_boost(bool state)
557 567
558/** 568/**
559 * Selects an audio source for recording or playback 569 * Selects an audio source for recording or playback
560 * powers/unpowers related devices. 570 * powers/unpowers related devices and sets up monitoring.
561 * Here because it calls app code and used only for HAVE_RECORDING atm. 571 * Here because it calls app code and used only for HAVE_RECORDING atm.
562 * Would like it in pcm_record.c. 572 * Would like it in pcm_record.c.
573 *
574 * Behaves like a firmware function in that it does not use global settings
575 * to determine the state.
576 *
577 * The order of setting monitoring may need tweaking dependent upon the
578 * selected source to get the smoothest transition.
563 */ 579 */
564#if defined(HAVE_UDA1380) 580#if defined(HAVE_UDA1380)
565#define ac_disable_recording uda1380_disable_recording 581#define ac_disable_recording uda1380_disable_recording
@@ -571,7 +587,13 @@ static void rec_boost(bool state)
571#define ac_set_monitor tlv320_set_monitor 587#define ac_set_monitor tlv320_set_monitor
572#endif 588#endif
573 589
574void rec_set_source(int source, int flags) 590#ifdef HAVE_SPDIF_IN
591#define rec_spdif_set_monitor(m) audio_spdif_set_monitor(m)
592#else
593#define rec_spdif_set_monitor(m)
594#endif
595
596void rec_set_source(int source, unsigned flags)
575{ 597{
576 /* Prevent pops from unneeded switching */ 598 /* Prevent pops from unneeded switching */
577 static int last_source = AUDIO_SRC_PLAYBACK; 599 static int last_source = AUDIO_SRC_PLAYBACK;
@@ -586,7 +608,9 @@ void rec_set_source(int source, int flags)
586 608
587 /** Do power up/down of associated device(s) **/ 609 /** Do power up/down of associated device(s) **/
588 610
611 /** SPDIF **/
589#ifdef HAVE_SPDIF_IN 612#ifdef HAVE_SPDIF_IN
613 /* Always boost for SPDIF */
590 if ((source == AUDIO_SRC_SPDIF) != (source == last_source)) 614 if ((source == AUDIO_SRC_SPDIF) != (source == last_source))
591 rec_boost(source == AUDIO_SRC_SPDIF); 615 rec_boost(source == AUDIO_SRC_SPDIF);
592 616
@@ -595,10 +619,11 @@ void rec_set_source(int source, int flags)
595 both optical in and out is controlled by the same power source, which is 619 both optical in and out is controlled by the same power source, which is
596 the case on H1x0. */ 620 the case on H1x0. */
597 spdif_power_enable((source == AUDIO_SRC_SPDIF) || 621 spdif_power_enable((source == AUDIO_SRC_SPDIF) ||
598 global_settings.spdif_enable); 622 audio_get_spdif_power_setting());
599#endif 623#endif
600#endif 624#endif
601 625
626 /** Tuner **/
602#ifdef CONFIG_TUNER 627#ifdef CONFIG_TUNER
603 /* Switch radio off or on per source and flags. */ 628 /* Switch radio off or on per source and flags. */
604 if (source != AUDIO_SRC_FMRADIO) 629 if (source != AUDIO_SRC_FMRADIO)
@@ -612,12 +637,15 @@ void rec_set_source(int source, int flags)
612 switch (source) 637 switch (source)
613 { 638 {
614 default: /* playback - no recording */ 639 default: /* playback - no recording */
640 source = AUDIO_SRC_PLAYBACK;
641 case AUDIO_SRC_PLAYBACK:
615 pm_playback = true; 642 pm_playback = true;
616 if (source == last_source) 643 if (source == last_source)
617 break; 644 break;
618 ac_disable_recording(); 645 ac_disable_recording();
619 ac_set_monitor(false); 646 ac_set_monitor(false);
620 pcm_rec_mux(0); /* line in */ 647 pcm_rec_mux(0); /* line in */
648 rec_spdif_set_monitor(-1); /* silence it */
621 break; 649 break;
622 650
623 case AUDIO_SRC_MIC: /* recording only */ 651 case AUDIO_SRC_MIC: /* recording only */
@@ -625,6 +653,7 @@ void rec_set_source(int source, int flags)
625 break; 653 break;
626 ac_enable_recording(true); /* source mic */ 654 ac_enable_recording(true); /* source mic */
627 pcm_rec_mux(0); /* line in */ 655 pcm_rec_mux(0); /* line in */
656 rec_spdif_set_monitor(0);
628 break; 657 break;
629 658
630 case AUDIO_SRC_LINEIN: /* recording only */ 659 case AUDIO_SRC_LINEIN: /* recording only */
@@ -632,29 +661,20 @@ void rec_set_source(int source, int flags)
632 break; 661 break;
633 pcm_rec_mux(0); /* line in */ 662 pcm_rec_mux(0); /* line in */
634 ac_enable_recording(false); /* source line */ 663 ac_enable_recording(false); /* source line */
664 rec_spdif_set_monitor(0);
635 break; 665 break;
636 666
637#ifdef HAVE_SPDIF_IN 667#ifdef HAVE_SPDIF_IN
638 case AUDIO_SRC_SPDIF: /* recording only */ 668 case AUDIO_SRC_SPDIF: /* recording only */
639 if (recording) 669 if (source == last_source)
640 { 670 break;
641 /* This was originally done in audio_set_recording_options only */ 671 ac_disable_recording();
642#ifdef HAVE_SPDIF_POWER 672 audio_spdif_set_monitor(1);
643 EBU1CONFIG = global_settings.spdif_enable ? (1 << 2) : 0;
644 /* Input source is EBUin1, Feed-through monitoring if desired */
645#else
646 EBU1CONFIG = (1 << 2);
647 /* Input source is EBUin1, Feed-through monitoring */
648#endif
649 }
650
651 if (source != last_source)
652 uda1380_disable_recording();
653 break; 673 break;
654#endif /* HAVE_SPDIF_IN */ 674#endif /* HAVE_SPDIF_IN */
655 675
656#ifdef HAVE_FMRADIO_IN 676#ifdef HAVE_FMRADIO_IN
657 case AUDIO_SRC_FMRADIO: 677 case AUDIO_SRC_FMRADIO: /* recording and playback */
658 if (!recording) 678 if (!recording)
659 { 679 {
660 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), 680 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
@@ -687,6 +707,8 @@ void rec_set_source(int source, int flags)
687 tlv320_set_monitor(true); /* analog bypass */ 707 tlv320_set_monitor(true); /* analog bypass */
688 } 708 }
689#endif 709#endif
710
711 rec_spdif_set_monitor(0);
690 break; 712 break;
691/* #elif defined(CONFIG_TUNER) */ 713/* #elif defined(CONFIG_TUNER) */
692/* Have radio but cannot record it */ 714/* Have radio but cannot record it */
@@ -702,33 +724,50 @@ void rec_set_source(int source, int flags)
702} /* rec_set_source */ 724} /* rec_set_source */
703#endif /* CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) */ 725#endif /* CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) */
704 726
705/* steal the mp3 buffer then actually set options */ 727void rec_init_recording_options(struct audio_recording_options *options)
706void rec_set_recording_options(int frequency, int quality, 728{
707 int source, int source_flags, 729 options->rec_source = global_settings.rec_source;
708 int channel_mode, bool editable, 730 options->rec_frequency = global_settings.rec_frequency;
709 int prerecord_time) 731 options->rec_channels = global_settings.rec_channels;
732 options->rec_prerecord_time = global_settings.rec_prerecord_time;
733#if CONFIG_CODEC == SWCODEC
734 options->rec_source_flags = 0;
735 options->enc_config.rec_format = global_settings.rec_format;
736 global_to_encoder_config(&options->enc_config);
737#else
738 options->rec_quality = global_settings.rec_quality;
739 options->rec_editable = global_settings.rec_editable;
740#endif
741}
742
743void rec_set_recording_options(struct audio_recording_options *options)
710{ 744{
711#if CONFIG_CODEC != SWCODEC 745#if CONFIG_CODEC != SWCODEC
712 if (global_settings.rec_prerecord_time) 746 if (global_settings.rec_prerecord_time)
713#endif
714 talk_buffer_steal(); /* will use the mp3 buffer */ 747 talk_buffer_steal(); /* will use the mp3 buffer */
748#endif
749
750#ifdef HAVE_SPDIF_IN
751#ifdef HAVE_SPDIF_POWER
752 audio_set_spdif_power_setting(global_settings.spdif_enable);
753#endif
754#endif
715 755
716#if CONFIG_CODEC == SWCODEC 756#if CONFIG_CODEC == SWCODEC
717 rec_set_source(source, source_flags | SRCF_RECORDING); 757 rec_set_source(options->rec_source,
718#else 758 options->rec_source_flags | SRCF_RECORDING);
719 (void)source_flags;
720#endif 759#endif
721 760
722 audio_set_recording_options(frequency, quality, source, 761 audio_set_recording_options(options);
723 channel_mode, editable, prerecord_time);
724} 762}
725 763
726static char path_buffer[MAX_PATH];
727
728/* steals mp3 buffer, creates unique filename and starts recording */ 764/* steals mp3 buffer, creates unique filename and starts recording */
729void rec_record(void) 765void rec_record(void)
730{ 766{
767#if CONFIG_CODEC != SWCODEC
731 talk_buffer_steal(); /* we use the mp3 buffer */ 768 talk_buffer_steal(); /* we use the mp3 buffer */
769#endif
770 IF_CNFN_NUM_(file_number = -1;) /* Hit disk for number */
732 audio_record(rec_create_filename(path_buffer)); 771 audio_record(rec_create_filename(path_buffer));
733} 772}
734 773
@@ -753,7 +792,6 @@ static void trigger_listener(int trigger_status)
753 case TRIG_GO: 792 case TRIG_GO:
754 if((audio_status() & AUDIO_STATUS_RECORD) != AUDIO_STATUS_RECORD) 793 if((audio_status() & AUDIO_STATUS_RECORD) != AUDIO_STATUS_RECORD)
755 { 794 {
756 talk_buffer_steal(); /* we use the mp3 buffer */
757 rec_record(); 795 rec_record();
758 /* give control to mpeg thread so that it can start 796 /* give control to mpeg thread so that it can start
759 recording */ 797 recording */
@@ -831,6 +869,8 @@ bool recording_screen(bool no_source)
831 ID2P(LANG_GIGABYTE) 869 ID2P(LANG_GIGABYTE)
832 }; 870 };
833 871
872 struct audio_recording_options rec_options;
873
834 global_settings.recscreen_on = true; 874 global_settings.recscreen_on = true;
835 cursor = 0; 875 cursor = 0;
836#if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR) 876#if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR)
@@ -838,35 +878,26 @@ bool recording_screen(bool no_source)
838#endif 878#endif
839 879
840#if CONFIG_CODEC == SWCODEC 880#if CONFIG_CODEC == SWCODEC
841 audio_stop();
842 voice_stop();
843 /* recording_menu gets messed up: so reset talk_menu */ 881 /* recording_menu gets messed up: so reset talk_menu */
844 talk_menu = global_settings.talk_menu; 882 talk_menu = global_settings.talk_menu;
845 global_settings.talk_menu = 0; 883 global_settings.talk_menu = 0;
884 /* audio_init_recording stops anything playing when it takes the audio
885 buffer */
846#else 886#else
847 /* Yes, we use the D/A for monitoring */ 887 /* Yes, we use the D/A for monitoring */
848 peak_meter_enabled = true; 888 peak_meter_enabled = true;
849 peak_meter_playback(true); 889 peak_meter_playback(true);
850#endif 890#endif
851 891
852#if CONFIG_CODEC == SWCODEC
853 audio_init_recording(talk_get_bufsize());
854#else
855 audio_init_recording(0); 892 audio_init_recording(0);
856#endif
857 sound_set_volume(global_settings.volume); 893 sound_set_volume(global_settings.volume);
858 894
859#ifdef HAVE_AGC 895#ifdef HAVE_AGC
860 peak_meter_get_peakhold(&peak_l, &peak_r); 896 peak_meter_get_peakhold(&peak_l, &peak_r);
861#endif 897#endif
862 898
863 rec_set_recording_options(global_settings.rec_frequency, 899 rec_init_recording_options(&rec_options);
864 global_settings.rec_quality, 900 rec_set_recording_options(&rec_options);
865 global_settings.rec_source,
866 0,
867 global_settings.rec_channels,
868 global_settings.rec_editable,
869 global_settings.rec_prerecord_time);
870 901
871 set_gain(); 902 set_gain();
872 settings_apply_trigger(); 903 settings_apply_trigger();
@@ -1025,7 +1056,6 @@ bool recording_screen(bool no_source)
1025 { 1056 {
1026 /* manual recording */ 1057 /* manual recording */
1027 have_recorded = true; 1058 have_recorded = true;
1028 talk_buffer_steal(); /* we use the mp3 buffer */
1029 rec_record(); 1059 rec_record();
1030 last_seconds = 0; 1060 last_seconds = 0;
1031 if (talk_menu) 1061 if (talk_menu)
@@ -1253,16 +1283,10 @@ bool recording_screen(bool no_source)
1253#if CONFIG_CODEC == SWCODEC 1283#if CONFIG_CODEC == SWCODEC
1254 /* reinit after submenu exit */ 1284 /* reinit after submenu exit */
1255 audio_close_recording(); 1285 audio_close_recording();
1256 audio_init_recording(talk_get_bufsize()); 1286 audio_init_recording(0);
1257#endif 1287#endif
1258 rec_set_recording_options( 1288 rec_init_recording_options(&rec_options);
1259 global_settings.rec_frequency, 1289 rec_set_recording_options(&rec_options);
1260 global_settings.rec_quality,
1261 global_settings.rec_source,
1262 0,
1263 global_settings.rec_channels,
1264 global_settings.rec_editable,
1265 global_settings.rec_prerecord_time);
1266 1290
1267 if(rec_create_directory() > 0) 1291 if(rec_create_directory() > 0)
1268 have_recorded = true; 1292 have_recorded = true;
@@ -1739,11 +1763,7 @@ bool recording_screen(bool no_source)
1739 } 1763 }
1740 } /* end while(!done) */ 1764 } /* end while(!done) */
1741 1765
1742#if CONFIG_CODEC == SWCODEC
1743 audio_stat = pcm_rec_status();
1744#else
1745 audio_stat = audio_status(); 1766 audio_stat = audio_status();
1746#endif
1747 if (audio_stat & AUDIO_STATUS_ERROR) 1767 if (audio_stat & AUDIO_STATUS_ERROR)
1748 { 1768 {
1749 gui_syncsplash(0, true, str(LANG_SYSFONT_DISK_FULL)); 1769 gui_syncsplash(0, true, str(LANG_SYSFONT_DISK_FULL));
@@ -1804,11 +1824,22 @@ bool recording_screen(bool no_source)
1804#if CONFIG_KEYPAD == RECORDER_PAD 1824#if CONFIG_KEYPAD == RECORDER_PAD
1805bool f2_rec_screen(void) 1825bool f2_rec_screen(void)
1806{ 1826{
1827 static const char* const freq_str[6] =
1828 {
1829 "44.1kHz",
1830 "48kHz",
1831 "32kHz",
1832 "22.05kHz",
1833 "24kHz",
1834 "16kHz"
1835 };
1836
1807 bool exit = false; 1837 bool exit = false;
1808 bool used = false; 1838 bool used = false;
1809 int w, h, i; 1839 int w, h, i;
1810 char buf[32]; 1840 char buf[32];
1811 int button; 1841 int button;
1842 struct audio_recording_options rec_options;
1812 1843
1813 FOR_NB_SCREENS(i) 1844 FOR_NB_SCREENS(i)
1814 { 1845 {
@@ -1919,13 +1950,8 @@ bool f2_rec_screen(void)
1919 } 1950 }
1920 } 1951 }
1921 1952
1922 rec_set_recording_options(global_settings.rec_frequency, 1953 rec_init_recording_options(&rec_options);
1923 global_settings.rec_quality, 1954 rec_set_recording_options(&rec_options);
1924 global_settings.rec_source,
1925 0,
1926 global_settings.rec_channels,
1927 global_settings.rec_editable,
1928 global_settings.rec_prerecord_time);
1929 1955
1930 set_gain(); 1956 set_gain();
1931 1957
@@ -1948,6 +1974,8 @@ bool f3_rec_screen(void)
1948 str(LANG_SYSFONT_RECORDING_SRC_LINE), 1974 str(LANG_SYSFONT_RECORDING_SRC_LINE),
1949 str(LANG_SYSFONT_RECORDING_SRC_DIGITAL) 1975 str(LANG_SYSFONT_RECORDING_SRC_DIGITAL)
1950 }; 1976 };
1977 struct audio_recording_options rec_options;
1978
1951 FOR_NB_SCREENS(i) 1979 FOR_NB_SCREENS(i)
1952 { 1980 {
1953 screens[i].setfont(FONT_SYSFIXED); 1981 screens[i].setfont(FONT_SYSFIXED);
@@ -2019,13 +2047,8 @@ bool f3_rec_screen(void)
2019 } 2047 }
2020 } 2048 }
2021 2049
2022 rec_set_recording_options(global_settings.rec_frequency, 2050 rec_init_recording_options(&rec_options);
2023 global_settings.rec_quality, 2051 rec_set_recording_options(&rec_options);
2024 global_settings.rec_source,
2025 0,
2026 global_settings.rec_channels,
2027 global_settings.rec_editable,
2028 global_settings.rec_prerecord_time);
2029 2052
2030 set_gain(); 2053 set_gain();
2031 2054
@@ -2066,23 +2089,30 @@ unsigned long audio_num_recorded_bytes(void)
2066} 2089}
2067 2090
2068#if CONFIG_CODEC == SWCODEC 2091#if CONFIG_CODEC == SWCODEC
2069void rec_set_source(int source, int flags) 2092void rec_set_source(int source, unsigned flags)
2070{ 2093{
2071 source = source; 2094 source = source;
2072 flags = flags; 2095 flags = flags;
2073} 2096}
2074#endif
2075 2097
2076void audio_set_recording_options(int frequency, int quality, 2098#ifdef HAVE_SPDIF_IN
2077 int source, int channel_mode, 2099#ifdef HAVE_SPDIF_POWER
2078 bool editable, int prerecord_time) 2100void audio_set_spdif_power_setting(bool on)
2079{ 2101{
2080 frequency = frequency; 2102 on = on;
2081 quality = quality; 2103}
2082 source = source; 2104
2083 channel_mode = channel_mode; 2105bool audio_get_spdif_power_setting(void)
2084 editable = editable; 2106{
2085 prerecord_time = prerecord_time; 2107 return true;
2108}
2109#endif /* HAVE_SPDIF_POWER */
2110#endif /* HAVE_SPDIF_IN */
2111#endif /* CONFIG_CODEC == SWCODEC */
2112
2113void audio_set_recording_options(struct audio_recording_options *options)
2114{
2115 options = options;
2086} 2116}
2087 2117
2088void audio_set_recording_gain(int left, int right, int type) 2118void audio_set_recording_gain(int left, int right, int type)
@@ -2104,7 +2134,7 @@ void audio_resume_recording(void)
2104{ 2134{
2105} 2135}
2106 2136
2107void pcm_rec_get_peaks(int *left, int *right) 2137void pcm_calculate_rec_peaks(int *left, int *right)
2108{ 2138{
2109 if (left) 2139 if (left)
2110 *left = 0; 2140 *left = 0;
diff --git a/apps/recorder/recording.h b/apps/recorder/recording.h
index aa216e757f..a977efa749 100644
--- a/apps/recorder/recording.h
+++ b/apps/recorder/recording.h
@@ -32,15 +32,16 @@ int rec_create_directory(void);
32#define SRCF_FMRADIO_PLAYING 0x0000 /* default */ 32#define SRCF_FMRADIO_PLAYING 0x0000 /* default */
33#define SRCF_FMRADIO_PAUSED 0x2000 33#define SRCF_FMRADIO_PAUSED 0x2000
34#endif 34#endif
35void rec_set_source(int source, int flags); 35void rec_set_source(int source, unsigned flags);
36#endif /* CONFIG_CODEC == SW_CODEC */ 36#endif /* CONFIG_CODEC == SW_CODEC */
37 37
38/* Initializes a recording_options structure with global settings.
39 pass returned data to audio_set_recording_options or
40 rec_set_recording_options */
41void rec_init_recording_options(struct audio_recording_options *options);
38/* steals mp3 buffer, sets source and then options */ 42/* steals mp3 buffer, sets source and then options */
39/* SRCF_RECORDING is implied */ 43/* SRCF_RECORDING is implied for SWCODEC */
40void rec_set_recording_options(int frequency, int quality, 44void rec_set_recording_options(struct audio_recording_options *options);
41 int source, int source_flags,
42 int channel_mode, bool editable,
43 int prerecord_time);
44 45
45/* steals mp3 buffer, creates unique filename and starts recording */ 46/* steals mp3 buffer, creates unique filename and starts recording */
46void rec_record(void); 47void rec_record(void);
diff --git a/apps/settings.c b/apps/settings.c
index a4320eda7b..ec96cc760b 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -90,13 +90,16 @@ const char rec_base_directory[] = REC_BASE_DIR;
90#include "pcmbuf.h" 90#include "pcmbuf.h"
91#include "pcm_playback.h" 91#include "pcm_playback.h"
92#include "dsp.h" 92#include "dsp.h"
93#ifdef HAVE_RECORDING
94#include "enc_config.h"
93#endif 95#endif
96#endif /* CONFIG_CODEC == SWCODEC */
94 97
95#ifdef HAVE_WM8758 98#ifdef HAVE_WM8758
96#include "eq_menu.h" 99#include "eq_menu.h"
97#endif 100#endif
98 101
99#define CONFIG_BLOCK_VERSION 55 102#define CONFIG_BLOCK_VERSION 56
100#define CONFIG_BLOCK_SIZE 512 103#define CONFIG_BLOCK_SIZE 512
101#define RTC_BLOCK_SIZE 44 104#define RTC_BLOCK_SIZE 44
102 105
@@ -514,7 +517,7 @@ static const struct bit_entry hd_bits[] =
514 {1, S_O(rec_editable), false, "editable recordings", off_on }, 517 {1, S_O(rec_editable), false, "editable recordings", off_on },
515#endif /* CONFIG_CODEC == MAS3587F */ 518#endif /* CONFIG_CODEC == MAS3587F */
516 519
517#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) 520#if CONFIG_CODEC == SWCODEC
518#ifdef HAVE_UDA1380 521#ifdef HAVE_UDA1380
519 {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */ 522 {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */
520#endif 523#endif
@@ -524,16 +527,20 @@ static const struct bit_entry hd_bits[] =
524#endif 527#endif
525 {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */ 528 {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */
526 {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */ 529 {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */
527#if 0 /* Till samplerates are added for SWCODEC */ 530 {REC_FREQ_CFG_NUM_BITS, S_O(rec_frequency), REC_FREQ_DEFAULT,
528 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */ 531 "rec frequency", REC_FREQ_CFG_VAL_LIST },
529 "rec frequency", "44,48,32,22,24,16" }, 532 {REC_FORMAT_CFG_NUM_BITS ,S_O(rec_format), REC_FORMAT_DEFAULT,
530#else 533 "rec format", REC_FORMAT_CFG_VAL_LIST },
531 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */ 534 /** Encoder settings start - keep these together **/
532 "rec frequency", "44" }, 535 /* mp3_enc */
533#endif 536 {5,S_O(mp3_enc_config.bitrate), MP3_ENC_BITRATE_CFG_DEFAULT,
534 537 "mp3_enc bitrate", MP3_ENC_BITRATE_CFG_VALUE_LIST },
535 {4, S_O(rec_quality), 4 /* MP3 L3 192 kBit/s */, "rec quality", NULL }, 538 /* wav_enc */
536#endif /* CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) */ 539 /* (no settings yet) */
540 /* wavpack_enc */
541 /* (no settings yet) */
542 /** Encoder settings end **/
543#endif /* CONFIG_CODEC == SWCODEC */
537 544
538 /* values for the trigger */ 545 /* values for the trigger */
539 {8 | SIGNED, S_O(rec_start_thres), -35, "trigger start threshold", NULL}, 546 {8 | SIGNED, S_O(rec_start_thres), -35, "trigger start threshold", NULL},
@@ -1301,6 +1308,11 @@ void settings_apply(void)
1301 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off); 1308 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off);
1302#endif 1309#endif
1303#endif /* CONFIG_BACKLIGHT */ 1310#endif /* CONFIG_BACKLIGHT */
1311
1312 /* This should stay last */
1313#if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
1314 enc_global_settings_apply();
1315#endif
1304} 1316}
1305 1317
1306 1318
@@ -1727,13 +1739,13 @@ static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
1727 } 1739 }
1728} 1740}
1729 1741
1730
1731bool settings_save_config(void) 1742bool settings_save_config(void)
1732{ 1743{
1733 int fd; 1744 int fd;
1734 char filename[MAX_PATH]; 1745 char filename[MAX_PATH];
1735 1746
1736 create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2); 1747 create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2
1748 IF_CNFN_NUM_(, NULL));
1737 1749
1738 /* allow user to modify filename */ 1750 /* allow user to modify filename */
1739 while (true) { 1751 while (true) {
@@ -1887,6 +1899,10 @@ void settings_reset(void) {
1887 global_settings.kbd_file[0] = '\0'; 1899 global_settings.kbd_file[0] = '\0';
1888#endif 1900#endif
1889 global_settings.hold_lr_for_scroll_in_list = true; 1901 global_settings.hold_lr_for_scroll_in_list = true;
1902
1903#if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
1904 enc_global_settings_reset();
1905#endif
1890} 1906}
1891 1907
1892bool set_bool(const char* string, bool* variable ) 1908bool set_bool(const char* string, bool* variable )
diff --git a/apps/settings.h b/apps/settings.h
index 435d8e9ce2..09d4974eee 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -29,6 +29,10 @@
29#include "tagcache.h" 29#include "tagcache.h"
30#include "button.h" 30#include "button.h"
31 31
32#if CONFIG_CODEC == SWCODEC
33#include "audio.h"
34#endif
35
32#ifdef HAVE_BACKLIGHT_BRIGHTNESS 36#ifdef HAVE_BACKLIGHT_BRIGHTNESS
33#include "backlight.h" /* for [MIN|MAX]_BRIGHTNESS_SETTING */ 37#include "backlight.h" /* for [MIN|MAX]_BRIGHTNESS_SETTING */
34#endif 38#endif
@@ -142,18 +146,22 @@ struct user_settings
142 int crossfade_fade_out_mixmode; /* Fade out mode (0=crossfade,1=mix) */ 146 int crossfade_fade_out_mixmode; /* Fade out mode (0=crossfade,1=mix) */
143#endif 147#endif
144 148
149#if CONFIG_CODEC == SWCODEC
150 int rec_format; /* record format index */
151#else
145 int rec_quality; /* 0-7 */ 152 int rec_quality; /* 0-7 */
146 int rec_source; /* 0=mic, 1=line, 2=S/PDIF */ 153#endif /* CONFIG_CODEC == SWCODEC */
147 int rec_frequency; /* 0 = 44.1kHz 154 int rec_source; /* 0=mic, 1=line, 2=S/PDIF, 2 or 3=FM Radio */
155 int rec_frequency; /* 0 = 44.1kHz (depends on target)
148 1 = 48kHz 156 1 = 48kHz
149 2 = 32kHz 157 2 = 32kHz
150 3 = 22.05kHz 158 3 = 22.05kHz
151 4 = 24kHz 159 4 = 24kHz
152 5 = 16kHz */ 160 5 = 16kHz */
153 int rec_channels; /* 0=Stereo, 1=Mono */ 161 int rec_channels; /* 0=Stereo, 1=Mono */
154 int rec_mic_gain; /* 0-15 */ 162 int rec_mic_gain; /* depends on target */
155 int rec_left_gain; /* 0-15 */ 163 int rec_left_gain; /* depends on target */
156 int rec_right_gain; /* 0-15 */ 164 int rec_right_gain; /* depands on target */
157 bool rec_editable; /* true means that the bit reservoir is off */ 165 bool rec_editable; /* true means that the bit reservoir is off */
158 bool recscreen_on; /* true if using the recording screen */ 166 bool recscreen_on; /* true if using the recording screen */
159 167
@@ -504,6 +512,20 @@ struct user_settings
504#endif 512#endif
505 bool audioscrobbler; /* Audioscrobbler logging */ 513 bool audioscrobbler; /* Audioscrobbler logging */
506 514
515 /* If values are just added to the end, no need to bump plugin API
516 version. */
517 /* new stuff to be added at the end */
518
519#if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
520 /* Encoder Settings Start - keep these together */
521 struct mp3_enc_config mp3_enc_config;
522#if 0 /* These currently contain no members but their places in line
523 should be held */
524 struct wav_enc_config wav_enc_config;
525 struct wavpack_enc_config wavpack_enc_config;
526#endif
527 /* Encoder Settings End */
528#endif /* CONFIG_CODEC == SWCODEC */
507}; 529};
508 530
509enum optiontype { INT, BOOL }; 531enum optiontype { INT, BOOL };
@@ -584,7 +606,7 @@ extern const char rec_base_directory[];
584 606
585/* argument bits for settings_load() */ 607/* argument bits for settings_load() */
586#define SETTINGS_RTC 1 /* only the settings from the RTC nonvolatile RAM */ 608#define SETTINGS_RTC 1 /* only the settings from the RTC nonvolatile RAM */
587#define SETTINGS_HD 2 /* only the settings fron the disk sector */ 609#define SETTINGS_HD 2 /* only the settings from the disk sector */
588#define SETTINGS_ALL 3 /* both */ 610#define SETTINGS_ALL 3 /* both */
589 611
590/* repeat mode options */ 612/* repeat mode options */
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index c10ba9417e..fb766d604c 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -54,6 +54,10 @@
54#include "dsp.h" 54#include "dsp.h"
55#include "eq_menu.h" 55#include "eq_menu.h"
56#include "pcmbuf.h" 56#include "pcmbuf.h"
57#ifdef HAVE_RECORDING
58#include "enc_config.h"
59#endif
60#include "general.h"
57#endif 61#endif
58#include "action.h" 62#include "action.h"
59 63
@@ -308,22 +312,20 @@ static bool recsource(void)
308{ 312{
309 int n_opts = AUDIO_NUM_SOURCES; 313 int n_opts = AUDIO_NUM_SOURCES;
310 314
311 struct opt_items names[AUDIO_NUM_SOURCES] = { 315 static const struct opt_items names[AUDIO_NUM_SOURCES] = {
312 { STR(LANG_RECORDING_SRC_MIC) }, 316 [AUDIO_SRC_MIC] = { STR(LANG_RECORDING_SRC_MIC) },
313 { STR(LANG_RECORDING_SRC_LINE) }, 317 [AUDIO_SRC_LINEIN] = { STR(LANG_RECORDING_SRC_LINE) },
314#ifdef HAVE_SPDIF_IN 318#ifdef HAVE_SPDIF_IN
315 { STR(LANG_RECORDING_SRC_DIGITAL) }, 319 [AUDIO_SRC_SPDIF] = { STR(LANG_RECORDING_SRC_DIGITAL) },
320#endif
321#ifdef HAVE_FMRADIO_IN
322 [AUDIO_SRC_FMRADIO] = { STR(LANG_FM_RADIO) }
316#endif 323#endif
317 }; 324 };
318 325
319 /* caveat: assumes it's the last item! */ 326 /* caveat: assumes it's the last item! */
320#ifdef HAVE_FMRADIO_IN 327#ifdef HAVE_FMRADIO_IN
321 if (radio_hardware_present()) 328 if (!radio_hardware_present())
322 {
323 names[AUDIO_SRC_FMRADIO].string = ID2P(LANG_FM_RADIO);
324 names[AUDIO_SRC_FMRADIO].voice_id = LANG_FM_RADIO;
325 }
326 else
327 n_opts--; 329 n_opts--;
328#endif 330#endif
329 331
@@ -332,28 +334,7 @@ static bool recsource(void)
332 n_opts, NULL ); 334 n_opts, NULL );
333} 335}
334 336
335/* To be removed when we add support for sample rates and channel settings */ 337#if CONFIG_CODEC == MAS3587F
336#if CONFIG_CODEC == SWCODEC
337static bool recquality(void)
338{
339 static const struct opt_items names[] = {
340 { "MP3 64 kBit/s", TALK_ID( 64, UNIT_KBIT) },
341 { "MP3 96 kBit/s", TALK_ID( 96, UNIT_KBIT) },
342 { "MP3 128 kBit/s", TALK_ID( 128, UNIT_KBIT) },
343 { "MP3 160 kBit/s", TALK_ID( 160, UNIT_KBIT) },
344 { "MP3 192 kBit/s", TALK_ID( 192, UNIT_KBIT) },
345 { "MP3 224 kBit/s", TALK_ID( 224, UNIT_KBIT) },
346 { "MP3 320 kBit/s", TALK_ID( 320, UNIT_KBIT) },
347 { "WV 900 kBit/s", TALK_ID( 900, UNIT_KBIT) },
348 { "WAV 1411 kBit/s", TALK_ID(1411, UNIT_KBIT) }
349 };
350
351 return set_option(str(LANG_RECORDING_QUALITY),
352 &global_settings.rec_quality, INT,
353 names, sizeof (names)/sizeof(struct opt_items),
354 NULL );
355}
356#elif CONFIG_CODEC == MAS3587F
357static bool recquality(void) 338static bool recquality(void)
358{ 339{
359 return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT, 340 return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
@@ -368,32 +349,182 @@ static bool receditable(void)
368} 349}
369#endif /* CONFIG_CODEC == MAS3587F */ 350#endif /* CONFIG_CODEC == MAS3587F */
370 351
352#if CONFIG_CODEC == SWCODEC
353/* Makes an options list from a source list of options and indexes */
354void make_options_from_indexes(const struct opt_items *src_names,
355 const long *src_indexes,
356 int n_indexes,
357 struct opt_items *dst_names)
358{
359 while (--n_indexes >= 0)
360 dst_names[n_indexes] = src_names[src_indexes[n_indexes]];
361} /* make_options_from_indexes */
362
363static bool recformat(void)
364{
365 static const struct opt_items names[REC_NUM_FORMATS] = {
366 [REC_FORMAT_MPA_L3] = { STR(LANG_AFMT_MPA_L3) },
367 [REC_FORMAT_WAVPACK] = { STR(LANG_AFMT_WAVPACK) },
368 [REC_FORMAT_PCM_WAV] = { STR(LANG_AFMT_PCM_WAV) },
369 };
370
371 int rec_format = global_settings.rec_format;
372 bool res = set_option(str(LANG_RECORDING_FORMAT), &rec_format, INT,
373 names, REC_NUM_FORMATS, NULL );
374
375 if (rec_format != global_settings.rec_format)
376 {
377 global_settings.rec_format = rec_format;
378 enc_global_settings_apply();
379 }
380
381 return res;
382} /* recformat */
383
384#endif /* CONFIG_CODEC == SWCODEC */
385
371static bool recfrequency(void) 386static bool recfrequency(void)
372{ 387{
373 static const struct opt_items names[] = { 388#if CONFIG_CODEC == MAS3587F
389 static const struct opt_items names[6] = {
374 { "44.1kHz", TALK_ID(44, UNIT_KHZ) }, 390 { "44.1kHz", TALK_ID(44, UNIT_KHZ) },
375#if CONFIG_CODEC != SWCODEC /* This is temporary */
376 { "48kHz", TALK_ID(48, UNIT_KHZ) }, 391 { "48kHz", TALK_ID(48, UNIT_KHZ) },
377 { "32kHz", TALK_ID(32, UNIT_KHZ) }, 392 { "32kHz", TALK_ID(32, UNIT_KHZ) },
378 { "22.05kHz", TALK_ID(22, UNIT_KHZ) }, 393 { "22.05kHz", TALK_ID(22, UNIT_KHZ) },
379 { "24kHz", TALK_ID(24, UNIT_KHZ) }, 394 { "24kHz", TALK_ID(24, UNIT_KHZ) },
380 { "16kHz", TALK_ID(16, UNIT_KHZ) } 395 { "16kHz", TALK_ID(16, UNIT_KHZ) }
381#endif
382 }; 396 };
383 return set_option(str(LANG_RECORDING_FREQUENCY), 397 return set_option(str(LANG_RECORDING_FREQUENCY),
384 &global_settings.rec_frequency, INT, 398 &global_settings.rec_frequency, INT,
385 names, sizeof(names)/sizeof(*names), NULL ); 399 names, 6, NULL );
400#endif /* CONFIG_CODEC == MAS3587F */
401
402#if CONFIG_CODEC == SWCODEC
403 static const struct opt_items names[REC_NUM_FREQ] = {
404 REC_HAVE_96_([REC_FREQ_96] = { "96kHz", TALK_ID(96, UNIT_KHZ) },)
405 REC_HAVE_88_([REC_FREQ_88] = { "88.2kHz", TALK_ID(88, UNIT_KHZ) },)
406 REC_HAVE_64_([REC_FREQ_64] = { "64kHz", TALK_ID(64, UNIT_KHZ) },)
407 REC_HAVE_48_([REC_FREQ_48] = { "48kHz", TALK_ID(48, UNIT_KHZ) },)
408 REC_HAVE_44_([REC_FREQ_44] = { "44.1kHz", TALK_ID(44, UNIT_KHZ) },)
409 REC_HAVE_32_([REC_FREQ_32] = { "32kHz", TALK_ID(32, UNIT_KHZ) },)
410 REC_HAVE_24_([REC_FREQ_24] = { "24kHz", TALK_ID(24, UNIT_KHZ) },)
411 REC_HAVE_22_([REC_FREQ_22] = { "22.05kHz", TALK_ID(22, UNIT_KHZ) },)
412 REC_HAVE_16_([REC_FREQ_16] = { "16kHz", TALK_ID(16, UNIT_KHZ) },)
413 REC_HAVE_12_([REC_FREQ_12] = { "12kHz", TALK_ID(12, UNIT_KHZ) },)
414 REC_HAVE_11_([REC_FREQ_11] = { "11.025kHz", TALK_ID(11, UNIT_KHZ) },)
415 REC_HAVE_8_( [REC_FREQ_8 ] = { "8kHz", TALK_ID( 8, UNIT_KHZ) },)
416 };
417
418 struct opt_items opts[REC_NUM_FREQ];
419 unsigned long table[REC_NUM_FREQ];
420 int n_opts;
421 int rec_frequency;
422 bool ret;
423
424#ifdef HAVE_SPDIF_IN
425 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
426 {
427 /* Inform user that frequency follows the source's frequency */
428 opts[0].string = ID2P(LANG_SOURCE_FREQUENCY);
429 opts[0].voice_id = LANG_SOURCE_FREQUENCY;
430 n_opts = 1;
431 rec_frequency = 0;
386} 432}
433 else
434#endif
435 {
436 struct encoder_caps caps;
437 struct encoder_config cfg;
438
439 cfg.rec_format = global_settings.rec_format;
440 global_to_encoder_config(&cfg);
441
442 if (!enc_get_caps(&cfg, &caps, true))
443 return false;
444
445 /* Construct samplerate menu based upon encoder settings */
446 n_opts = make_list_from_caps32(REC_SAMPR_CAPS, NULL,
447 caps.samplerate_caps, table);
448
449 if (n_opts == 0)
450 return false; /* No common flags...?? */
451
452 make_options_from_indexes(names, table, n_opts, opts);
453
454 /* Find closest rate that the potentially restricted list
455 comes to */
456 make_list_from_caps32(REC_SAMPR_CAPS, rec_freq_sampr,
457 caps.samplerate_caps, table);
458
459 rec_frequency = round_value_to_list32(
460 rec_freq_sampr[global_settings.rec_frequency],
461 table, n_opts, false);
462 }
463
464 ret = set_option(str(LANG_RECORDING_FREQUENCY),
465 &rec_frequency, INT, opts, n_opts, NULL );
466
467 if (!ret
468#ifdef HAVE_SPDIF_IN
469 && global_settings.rec_source != AUDIO_SRC_SPDIF
470#endif
471 )
472 {
473 /* Translate back to full index */
474 global_settings.rec_frequency =
475 round_value_to_list32(table[rec_frequency],
476 rec_freq_sampr,
477 REC_NUM_FREQ,
478 false);
479 }
480
481 return ret;
482#endif /* CONFIG_CODEC == SWCODEC */
483} /* recfrequency */
387 484
388static bool recchannels(void) 485static bool recchannels(void)
389{ 486{
390 static const struct opt_items names[] = { 487 static const struct opt_items names[CHN_NUM_MODES] = {
391 { STR(LANG_CHANNEL_STEREO) }, 488 [CHN_MODE_STEREO] = { STR(LANG_CHANNEL_STEREO) },
392 { STR(LANG_CHANNEL_MONO) } 489 [CHN_MODE_MONO] = { STR(LANG_CHANNEL_MONO) }
393 }; 490 };
491#if CONFIG_CODEC == MAS3587F
394 return set_option(str(LANG_RECORDING_CHANNELS), 492 return set_option(str(LANG_RECORDING_CHANNELS),
395 &global_settings.rec_channels, INT, 493 &global_settings.rec_channels, INT,
396 names, 2, NULL ); 494 names, CHN_NUM_MODES, NULL );
495#endif /* CONFIG_CODEC == MAS3587F */
496
497#if CONFIG_CODEC == SWCODEC
498 struct opt_items opts[CHN_NUM_MODES];
499 long table[CHN_NUM_MODES];
500 struct encoder_caps caps;
501 struct encoder_config cfg;
502 int n_opts;
503 int rec_channels;
504 bool ret;
505
506 cfg.rec_format = global_settings.rec_format;
507 global_to_encoder_config(&cfg);
508
509 if (!enc_get_caps(&cfg, &caps, true))
510 return false;
511
512 n_opts = make_list_from_caps32(CHN_CAP_ALL, NULL,
513 caps.channel_caps, table);
514
515 rec_channels = round_value_to_list32(global_settings.rec_channels,
516 table, n_opts, false);
517
518 make_options_from_indexes(names, table, n_opts, opts);
519
520 ret = set_option(str(LANG_RECORDING_CHANNELS), &rec_channels,
521 INT, opts, n_opts, NULL );
522
523 if (!ret)
524 global_settings.rec_channels = table[rec_channels];
525
526 return ret;
527#endif /* CONFIG_CODEC == SWCODEC */
397} 528}
398 529
399static bool rectimesplit(void) 530static bool rectimesplit(void)
@@ -1049,58 +1180,59 @@ bool rectrigger(void)
1049 action_signalscreenchange(); 1180 action_signalscreenchange();
1050 return retval; 1181 return retval;
1051} 1182}
1052#endif 1183#endif /* !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F */
1053 1184
1054bool recording_menu(bool no_source) 1185bool recording_menu(bool no_source)
1055{ 1186{
1056 int m; 1187 static const struct menu_item static_items[] = {
1057 int i = 0; 1188#if CONFIG_CODEC == MAS3587F
1058 struct menu_item items[13]; 1189 { ID2P(LANG_RECORDING_QUALITY), recquality },
1059 bool result;
1060
1061#if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == SWCODEC
1062 items[i].desc = ID2P(LANG_RECORDING_QUALITY);
1063 items[i++].function = recquality;
1064#endif 1190#endif
1065 items[i].desc = ID2P(LANG_RECORDING_FREQUENCY); 1191#if CONFIG_CODEC == SWCODEC
1066 items[i++].function = recfrequency; 1192 { ID2P(LANG_RECORDING_FORMAT), recformat },
1067 if(!no_source) { 1193 { ID2P(LANG_ENCODER_SETTINGS), enc_global_config_menu },
1068 items[i].desc = ID2P(LANG_RECORDING_SOURCE); 1194#endif
1069 items[i++].function = recsource; 1195 { ID2P(LANG_RECORDING_FREQUENCY), recfrequency },
1070 } 1196 { ID2P(LANG_RECORDING_SOURCE), recsource }, /* not shown if no_source */
1071 items[i].desc = ID2P(LANG_RECORDING_CHANNELS); 1197 { ID2P(LANG_RECORDING_CHANNELS), recchannels },
1072 items[i++].function = recchannels;
1073#if CONFIG_CODEC == MAS3587F 1198#if CONFIG_CODEC == MAS3587F
1074 items[i].desc = ID2P(LANG_RECORDING_EDITABLE); 1199 { ID2P(LANG_RECORDING_EDITABLE), receditable },
1075 items[i++].function = receditable;
1076#endif 1200#endif
1077 items[i].desc = ID2P(LANG_RECORD_TIMESPLIT); 1201 { ID2P(LANG_RECORD_TIMESPLIT), filesplitoptionsmenu },
1078 items[i++].function = filesplitoptionsmenu; 1202 { ID2P(LANG_RECORD_PRERECORD_TIME), recprerecord },
1079 items[i].desc = ID2P(LANG_RECORD_PRERECORD_TIME); 1203 { ID2P(LANG_RECORD_DIRECTORY), recdirectory },
1080 items[i++].function = recprerecord; 1204 { ID2P(LANG_RECORD_STARTUP), reconstartup },
1081 items[i].desc = ID2P(LANG_RECORD_DIRECTORY);
1082 items[i++].function = recdirectory;
1083 items[i].desc = ID2P(LANG_RECORD_STARTUP);
1084 items[i++].function = reconstartup;
1085#ifdef CONFIG_BACKLIGHT 1205#ifdef CONFIG_BACKLIGHT
1086 items[i].desc = ID2P(LANG_CLIP_LIGHT); 1206 { ID2P(LANG_CLIP_LIGHT), cliplight },
1087 items[i++].function = cliplight;
1088#endif 1207#endif
1089#if !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F 1208#if !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F
1090 items[i].desc = ID2P(LANG_RECORD_TRIGGER); 1209 { ID2P(LANG_RECORD_TRIGGER), rectrigger },
1091 items[i++].function = rectrigger;
1092#endif 1210#endif
1093#ifdef HAVE_AGC 1211#ifdef HAVE_AGC
1094 items[i].desc = ID2P(LANG_RECORD_AGC_PRESET); 1212 { ID2P(LANG_RECORD_AGC_PRESET), agc_preset },
1095 items[i++].function = agc_preset; 1213 { ID2P(LANG_RECORD_AGC_CLIPTIME), agc_cliptime },
1096 items[i].desc = ID2P(LANG_RECORD_AGC_CLIPTIME);
1097 items[i++].function = agc_cliptime;
1098#endif 1214#endif
1215 };
1099 1216
1100 m=menu_init( items, i, NULL, NULL, NULL, NULL); 1217 struct menu_item items[ARRAYLEN(static_items)];
1218 int i, n_items;
1219 int m;
1220
1221 bool result;
1222
1223 for (i = 0, n_items = 0; i < (int)ARRAYLEN(items); i++)
1224 {
1225 const struct menu_item *mi = &static_items[i];
1226 if (no_source && mi->function == recsource)
1227 continue;
1228 items[n_items++] = *mi;
1229 }
1230
1231 m = menu_init(items, n_items, NULL, NULL, NULL, NULL);
1101 result = menu_run(m); 1232 result = menu_run(m);
1102 menu_exit(m); 1233 menu_exit(m);
1103 1234
1104 return result; 1235 return result;
1105} 1236} /* recording_menu */
1106#endif 1237
1238#endif /* HAVE_RECORDING */
diff --git a/apps/status.c b/apps/status.c
index 2a57db0f89..75219d604c 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -46,7 +46,7 @@
46#ifdef CONFIG_TUNER 46#ifdef CONFIG_TUNER
47#include "radio.h" 47#include "radio.h"
48#endif 48#endif
49#if CONFIG_CODEC == SWCODEC 49#if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
50#include "pcm_record.h" 50#include "pcm_record.h"
51#endif 51#endif
52 52
@@ -87,10 +87,6 @@ int current_playmode(void)
87 } 87 }
88 88
89#ifdef HAVE_RECORDING 89#ifdef HAVE_RECORDING
90#if CONFIG_CODEC == SWCODEC
91 audio_stat = pcm_rec_status();
92#endif
93
94 if(audio_stat & AUDIO_STATUS_RECORD) 90 if(audio_stat & AUDIO_STATUS_RECORD)
95 { 91 {
96 if(audio_stat & AUDIO_STATUS_PAUSE) 92 if(audio_stat & AUDIO_STATUS_PAUSE)
diff --git a/apps/talk.c b/apps/talk.c
index d81aa082c9..018f6ed5ab 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -46,13 +46,17 @@
46 46
47 MASCODEC | MASCODEC | SWCODEC 47 MASCODEC | MASCODEC | SWCODEC
48 (playing) | (stopped) | 48 (playing) | (stopped) |
49 audiobuf-----------+-----------+----------- 49 audiobuf-----------+-----------+------------
50 audio | voice | thumbnail 50 audio | voice | thumbnail
51 |-----------|----------- filebuf 51 |-----------|------------
52 | thumbnail | voice 52 | thumbnail | voice
53 | |----------- 53 | |------------
54 | | filebuf
55 | |------------
54 | | audio 56 | | audio
55 audiobufend----------+-----------+----------- 57 | |------------
58 | | codec swap
59 audiobufend----------+-----------+------------
56 60
57 SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */ 61 SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */
58 62
@@ -102,7 +106,7 @@ struct queue_entry /* one entry of the internal queue */
102 106
103/***************** Globals *****************/ 107/***************** Globals *****************/
104 108
105static unsigned char* p_thumbnail; /* buffer for thumbnail */ 109static unsigned char* p_thumbnail = NULL; /* buffer for thumbnail */
106static long size_for_thumbnail; /* leftover buffer size for it */ 110static long size_for_thumbnail; /* leftover buffer size for it */
107static struct voicefile* p_voicefile; /* loaded voicefile */ 111static struct voicefile* p_voicefile; /* loaded voicefile */
108static bool has_voicefile; /* a voicefile file is present */ 112static bool has_voicefile; /* a voicefile file is present */
@@ -479,11 +483,14 @@ static void reset_state(void)
479 queue_write = queue_read = 0; /* reset the queue */ 483 queue_write = queue_read = 0; /* reset the queue */
480 p_voicefile = NULL; /* indicate no voicefile (trashed) */ 484 p_voicefile = NULL; /* indicate no voicefile (trashed) */
481#if CONFIG_CODEC == SWCODEC 485#if CONFIG_CODEC == SWCODEC
482 /* Allocate a dedicated thumbnail buffer */ 486 /* Allocate a dedicated thumbnail buffer - once */
483 size_for_thumbnail = audiobufend - audiobuf; 487 if (p_thumbnail == NULL)
484 if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE) 488 {
485 size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE; 489 size_for_thumbnail = audiobufend - audiobuf;
486 p_thumbnail = buffer_alloc(size_for_thumbnail); 490 if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE)
491 size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE;
492 p_thumbnail = buffer_alloc(size_for_thumbnail);
493 }
487#else 494#else
488 /* Just use the audiobuf, without allocating anything */ 495 /* Just use the audiobuf, without allocating anything */
489 p_thumbnail = audiobuf; 496 p_thumbnail = audiobuf;
diff --git a/apps/tree.c b/apps/tree.c
index 653da791a8..6465b50e6f 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -58,7 +58,9 @@
58#include "misc.h" 58#include "misc.h"
59#include "filetree.h" 59#include "filetree.h"
60#include "tagtree.h" 60#include "tagtree.h"
61#ifdef HAVE_RECORDING
61#include "recorder/recording.h" 62#include "recorder/recording.h"
63#endif
62#include "rtc.h" 64#include "rtc.h"
63#include "dircache.h" 65#include "dircache.h"
64#ifdef HAVE_TAGCACHE 66#ifdef HAVE_TAGCACHE
diff --git a/bootloader/main.c b/bootloader/main.c
index 99eb449151..0f3d706d7b 100644
--- a/bootloader/main.c
+++ b/bootloader/main.c
@@ -204,6 +204,7 @@ void main(void)
204 kernel_init(); 204 kernel_init();
205 205
206 set_cpu_frequency(CPUFREQ_NORMAL); 206 set_cpu_frequency(CPUFREQ_NORMAL);
207 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
207 208
208 set_irq_level(0); 209 set_irq_level(0);
209 lcd_init(); 210 lcd_init();
@@ -311,6 +312,9 @@ void main(void)
311#ifdef HAVE_ADJUSTABLE_CPU_FREQ 312#ifdef HAVE_ADJUSTABLE_CPU_FREQ
312 /* Set up waitstates for the peripherals */ 313 /* Set up waitstates for the peripherals */
313 set_cpu_frequency(0); /* PLL off */ 314 set_cpu_frequency(0); /* PLL off */
315#ifdef CPU_COLDFIRE
316 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
317#endif
314#endif 318#endif
315 319
316#ifdef HAVE_UDA1380 320#ifdef HAVE_UDA1380
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 1ec3c82616..df38169be3 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -4,6 +4,7 @@ logf.c
4#endif 4#endif
5backlight.c 5backlight.c
6buffer.c 6buffer.c
7general.c
7common/atoi.c 8common/atoi.c
8common/crc32.c 9common/crc32.c
9common/ctype.c 10common/ctype.c
@@ -45,7 +46,12 @@ target/coldfire/memcpy-coldfire.S
45target/coldfire/memmove-coldfire.S 46target/coldfire/memmove-coldfire.S
46target/coldfire/memset-coldfire.S 47target/coldfire/memset-coldfire.S
47target/coldfire/memset16-coldfire.S 48target/coldfire/memset16-coldfire.S
49#ifndef SIMULATOR
50#ifndef BOOTLOADER
51target/coldfire/pcm-coldfire.c
52#endif
48target/coldfire/system-coldfire.c 53target/coldfire/system-coldfire.c
54#endif
49#elif (CONFIG_CPU == SH7034) 55#elif (CONFIG_CPU == SH7034)
50target/sh/memcpy-sh.S 56target/sh/memcpy-sh.S
51target/sh/memmove-sh.S 57target/sh/memmove-sh.S
@@ -207,15 +213,21 @@ drivers/wm8731l.c
207#elif defined(HAVE_TLV320) && !defined(SIMULATOR) 213#elif defined(HAVE_TLV320) && !defined(SIMULATOR)
208drivers/tlv320.c 214drivers/tlv320.c
209#endif 215#endif
210#if (CONFIG_CODEC == SWCODEC) && !defined(SIMULATOR) 216#if (CONFIG_CODEC == SWCODEC) && !defined(BOOTLOADER)
211pcm_playback.c 217pcm_sampr.c
212#endif
213#if CONFIG_CODEC == SWCODEC
214replaygain.c 218replaygain.c
215#endif 219#ifndef SIMULATOR
216#if defined(CPU_COLDFIRE) && !defined(SIMULATOR) 220pcm_playback.c
221#endif /* SIMULATOR */
222#ifdef HAVE_RECORDING
223enc_base.c
224#if defined(CPU_COLDFIRE)
225#ifndef SIMULATOR
217pcm_record.c 226pcm_record.c
218#endif 227#endif /* SIMULATOR */
228#endif /* CPU_COLDFIRE */
229#endif /* HAVE_RECORDING */
230#endif /* SWCODEC && !BOOTLOADER */
219sound.c 231sound.c
220#if defined(IRIVER_IFP7XX_SERIES) && defined(STUB) 232#if defined(IRIVER_IFP7XX_SERIES) && defined(STUB)
221common/sscanf.c 233common/sscanf.c
diff --git a/firmware/drivers/tlv320.c b/firmware/drivers/tlv320.c
index abce31ef81..7c4bbbd1ee 100644
--- a/firmware/drivers/tlv320.c
+++ b/firmware/drivers/tlv320.c
@@ -82,7 +82,7 @@ void tlv320_init(void)
82 tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */ 82 tlv320_write_reg(REG_DAP, 0x00); /* No deemphasis */
83 tlv320_write_reg(REG_DAIF, DAIF_IWL_16 | DAIF_FOR_I2S); 83 tlv320_write_reg(REG_DAIF, DAIF_IWL_16 | DAIF_FOR_I2S);
84 tlv320_write_reg(REG_DIA, DIA_ACT); 84 tlv320_write_reg(REG_DIA, DIA_ACT);
85 tlv320_write_reg(REG_SRC, (1 << 5)); /* 44.1kHz */ 85 tlv320_set_frequency(-1); /* default */
86 /* All ON except ADC, MIC and LINE */ 86 /* All ON except ADC, MIC and LINE */
87 tlv320_write_reg(REG_PC, PC_ADC | PC_MIC | PC_LINE); 87 tlv320_write_reg(REG_PC, PC_ADC | PC_MIC | PC_LINE);
88} 88}
@@ -96,6 +96,32 @@ void tlv320_reset(void)
96} 96}
97 97
98/** 98/**
99 * Sets internal sample rate for DAC and ADC relative to MCLK
100 * Selection for frequency:
101 * Fs: tlv: with:
102 * 11025: 0 = MCLK/2 MCLK/2 SCLK, LRCK: Audio Clk / 16
103 * 22050: 0 = MCLK/2 MCLK SCLK, LRCK: Audio Clk / 8
104 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
105 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
106 */
107void tlv320_set_frequency(unsigned fsel)
108{
109 /* All rates available for 11.2896MHz besides 8.021 */
110 unsigned char values_src[3] =
111 {
112 /* Fs: */
113 (0x8 << 2) | SRC_CLKIN, /* 11025, 22050 */
114 (0x8 << 2), /* 44100 */
115 (0xf << 2), /* 88200 */
116 };
117
118 if (fsel >= ARRAYLEN(values_src))
119 fsel = 1;
120
121 tlv320_write_reg(REG_SRC, values_src[fsel]);
122}
123
124/**
99 * Sets left and right headphone volume 125 * Sets left and right headphone volume
100 * 126 *
101 * Left & Right: 48 .. 121 .. 127 => Volume -73dB (mute) .. +0 dB .. +6 dB 127 * Left & Right: 48 .. 121 .. 127 => Volume -73dB (mute) .. +0 dB .. +6 dB
@@ -142,7 +168,6 @@ void tlv320_set_recvol(int left, int right, int type)
142 value_aap &= ~AAP_MICB; 168 value_aap &= ~AAP_MICB;
143 169
144 tlv320_write_reg(REG_AAP, value_aap); 170 tlv320_write_reg(REG_AAP, value_aap);
145
146 } 171 }
147 else if (type == AUDIO_GAIN_LINEIN) 172 else if (type == AUDIO_GAIN_LINEIN)
148 { 173 {
@@ -180,15 +205,17 @@ void tlv320_mute(bool mute)
180} 205}
181 206
182/* Nice shutdown of TLV320 codec */ 207/* Nice shutdown of TLV320 codec */
183void tlv320_close() 208void tlv320_close(void)
184{ 209{
210 tlv320_mute(true);
211 sleep(HZ/8);
212
185 tlv320_write_reg(REG_PC, PC_OFF | PC_CLK | PC_OSC | PC_OUT | 213 tlv320_write_reg(REG_PC, PC_OFF | PC_CLK | PC_OSC | PC_OUT |
186 PC_DAC | PC_ADC | PC_MIC | PC_LINE); /* All OFF */ 214 PC_DAC | PC_ADC | PC_MIC | PC_LINE); /* All OFF */
187} 215}
188 216
189void tlv320_enable_recording(bool source_mic) 217void tlv320_enable_recording(bool source_mic)
190{ 218{
191 unsigned value_daif = tlv320_regs[REG_DAIF];
192 unsigned value_aap, value_pc; 219 unsigned value_aap, value_pc;
193 220
194 if (source_mic) 221 if (source_mic)
@@ -205,20 +232,12 @@ void tlv320_enable_recording(bool source_mic)
205 232
206 tlv320_write_reg(REG_PC, value_pc); 233 tlv320_write_reg(REG_PC, value_pc);
207 tlv320_write_reg(REG_AAP, value_aap); 234 tlv320_write_reg(REG_AAP, value_aap);
208
209 /* Enable MASTER mode (start sending I2S data to the CPU) */
210 value_daif |= DAIF_MS;
211 tlv320_write_reg(REG_DAIF, value_daif);
212} 235}
213 236
214void tlv320_disable_recording() 237void tlv320_disable_recording(void)
215{ 238{
216 unsigned value_pc = tlv320_regs[REG_PC]; 239 unsigned value_pc = tlv320_regs[REG_PC];
217 unsigned value_aap = tlv320_regs[REG_AAP]; 240 unsigned value_aap = tlv320_regs[REG_AAP];
218 unsigned value_daif = tlv320_regs[REG_DAIF];
219
220 value_daif &= ~DAIF_MS; /* disable MASTER mode */
221 tlv320_write_reg(REG_DAIF, value_daif);
222 241
223 value_aap |= AAP_MICM; /* mute MIC */ 242 value_aap |= AAP_MICM; /* mute MIC */
224 tlv320_write_reg(REG_PC, value_aap); 243 tlv320_write_reg(REG_PC, value_aap);
diff --git a/firmware/drivers/uda1380.c b/firmware/drivers/uda1380.c
index 241a117385..d6dfe6623b 100644
--- a/firmware/drivers/uda1380.c
+++ b/firmware/drivers/uda1380.c
@@ -49,9 +49,10 @@ short recgain_line;
49#define NUM_DEFAULT_REGS 13 49#define NUM_DEFAULT_REGS 13
50unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] = 50unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
51{ 51{
52 REG_0, EN_DAC | EN_INT | EN_DEC | SYSCLK_256FS | WSPLL_25_50, 52 REG_0, EN_DAC | EN_INT | EN_DEC | ADC_CLK | DAC_CLK |
53 SYSCLK_256FS | WSPLL_25_50,
53 REG_I2S, I2S_IFMT_IIS, 54 REG_I2S, I2S_IFMT_IIS,
54 REG_PWR, PON_BIAS, 55 REG_PWR, PON_PLL | PON_BIAS,
55 /* PON_HP & PON_DAC is enabled later */ 56 /* PON_HP & PON_DAC is enabled later */
56 REG_AMIX, AMIX_RIGHT(0x3f) | AMIX_LEFT(0x3f), 57 REG_AMIX, AMIX_RIGHT(0x3f) | AMIX_LEFT(0x3f),
57 /* 00=max, 3f=mute */ 58 /* 00=max, 3f=mute */
@@ -60,7 +61,7 @@ unsigned short uda1380_defaults[2*NUM_DEFAULT_REGS] =
60 REG_MIX_VOL, MIX_VOL_CH_1(0) | MIX_VOL_CH_2(0xff), 61 REG_MIX_VOL, MIX_VOL_CH_1(0) | MIX_VOL_CH_2(0xff),
61 /* 00=max, ff=mute */ 62 /* 00=max, ff=mute */
62 REG_EQ, EQ_MODE_MAX, 63 REG_EQ, EQ_MODE_MAX,
63 /* Bass and tremble = 0 dB */ 64 /* Bass and treble = 0 dB */
64 REG_MUTE, MUTE_MASTER | MUTE_CH2, 65 REG_MUTE, MUTE_MASTER | MUTE_CH2,
65 /* Mute everything to start with */ 66 /* Mute everything to start with */
66 REG_MIX_CTL, MIX_CTL_MIX, 67 REG_MIX_CTL, MIX_CTL_MIX,
@@ -192,6 +193,43 @@ void uda1380_reset(void)
192#endif 193#endif
193} 194}
194 195
196/**
197 * Sets frequency settings for DAC and ADC relative to MCLK
198 *
199 * Selection for frequency ranges:
200 * Fs: range: with:
201 * 11025: 0 = 6.25 to 12.5 MCLK/2 SCLK, LRCK: Audio Clk / 16
202 * 22050: 1 = 12.5 to 25 MCLK/2 SCLK, LRCK: Audio Clk / 8
203 * 44100: 2 = 25 to 50 MCLK SCLK, LRCK: Audio Clk / 4 (default)
204 * 88200: 3 = 50 to 100 MCLK SCLK, LRCK: Audio Clk / 2 <= TODO: Needs WSPLL
205 */
206void uda1380_set_frequency(unsigned fsel)
207{
208 static const unsigned short values_reg[4][2] =
209 {
210 /* Fs: */
211 { 0, WSPLL_625_125 | SYSCLK_512FS }, /* 11025 */
212 { 0, WSPLL_125_25 | SYSCLK_256FS }, /* 22050 */
213 { MIX_CTL_SEL_NS, WSPLL_25_50 | SYSCLK_256FS }, /* 44100 */
214 { MIX_CTL_SEL_NS, WSPLL_50_100 | SYSCLK_256FS }, /* 88200 */
215 };
216
217 const unsigned short *ent;
218
219 if (fsel >= ARRAYLEN(values_reg))
220 fsel = 2;
221
222 ent = values_reg[fsel];
223
224 /* Set WSPLL input frequency range or SYSCLK divider */
225 uda1380_regs[REG_0] &= ~0xf;
226 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | ent[1]);
227
228 /* Choose 3rd order or 5th order noise shaper */
229 uda1380_regs[REG_MIX_CTL] &= ~MIX_CTL_SEL_NS;
230 uda1380_write_reg(REG_MIX_CTL, uda1380_regs[REG_MIX_CTL] | ent[0]);
231}
232
195/* Initialize UDA1380 codec with default register values (uda1380_defaults) */ 233/* Initialize UDA1380 codec with default register values (uda1380_defaults) */
196int uda1380_init(void) 234int uda1380_init(void)
197{ 235{
@@ -227,30 +265,34 @@ void uda1380_close(void)
227 */ 265 */
228void uda1380_enable_recording(bool source_mic) 266void uda1380_enable_recording(bool source_mic)
229{ 267{
268 uda1380_regs[REG_0] &= ~(ADC_CLK | DAC_CLK);
230 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC); 269 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | EN_ADC);
231 270
232 if (source_mic) 271 if (source_mic)
233 { 272 {
234 /* VGA_GAIN: 0=0 dB, F=30dB */ 273 /* VGA_GAIN: 0=0 dB, F=30dB */
274 /* Output of left ADC is fed into right bitstream */
275 uda1380_regs[REG_PWR] &= ~(PON_PLL | PON_PGAR | PON_ADCR);
235 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_LNA | PON_ADCL); 276 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_LNA | PON_ADCL);
277 uda1380_regs[REG_ADC] &= ~SKIP_DCFIL;
236 uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC] & VGA_GAIN_MASK) 278 uda1380_write_reg(REG_ADC, (uda1380_regs[REG_ADC] & VGA_GAIN_MASK)
237 | SEL_LNA | SEL_MIC | EN_DCFIL); 279 | SEL_LNA | SEL_MIC | EN_DCFIL);
238 uda1380_write_reg(REG_PGA, 0); 280 uda1380_write_reg(REG_PGA, 0);
239 } else 281 }
282 else
240 { 283 {
241 /* PGA_GAIN: 0=0 dB, F=24dB */ 284 /* PGA_GAIN: 0=0 dB, F=24dB */
285 uda1380_regs[REG_PWR] &= ~(PON_PLL | PON_LNA);
242 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PGAL | PON_ADCL 286 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PGAL | PON_ADCL
243 | PON_PGAR | PON_ADCR); 287 | PON_PGAR | PON_ADCR);
244 uda1380_write_reg(REG_ADC, EN_DCFIL); 288 uda1380_write_reg(REG_ADC, EN_DCFIL);
245 uda1380_write_reg(REG_PGA, (uda1380_regs[REG_PGA] & PGA_GAIN_MASK) 289 uda1380_write_reg(REG_PGA, uda1380_regs[REG_PGA] & PGA_GAIN_MASK);
246 | PGA_GAINL(0) | PGA_GAINR(0));
247 } 290 }
248 291
249 sleep(HZ/8); 292 sleep(HZ/8);
250 293
251 uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER); 294 uda1380_write_reg(REG_I2S, uda1380_regs[REG_I2S] | I2S_MODE_MASTER);
252 uda1380_write_reg(REG_MIX_CTL, MIX_MODE(1)); 295 uda1380_write_reg(REG_MIX_CTL, MIX_MODE(1));
253
254} 296}
255 297
256/** 298/**
@@ -262,10 +304,13 @@ void uda1380_disable_recording(void)
262 sleep(HZ/8); 304 sleep(HZ/8);
263 305
264 uda1380_write_reg(REG_I2S, I2S_IFMT_IIS); 306 uda1380_write_reg(REG_I2S, I2S_IFMT_IIS);
265 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] & ~(PON_LNA | PON_ADCL 307
266 | PON_ADCR | PON_PGAL 308 uda1380_regs[REG_PWR] &= ~(PON_LNA | PON_ADCL | PON_ADCR | PON_PGAL | PON_PGAR);
267 | PON_PGAR)); 309 uda1380_write_reg(REG_PWR, uda1380_regs[REG_PWR] | PON_PLL);
268 uda1380_write_reg(REG_0, uda1380_regs[REG_0] & ~EN_ADC); 310
311 uda1380_regs[REG_0] &= ~EN_ADC;
312 uda1380_write_reg(REG_0, uda1380_regs[REG_0] | ADC_CLK | DAC_CLK);
313
269 uda1380_write_reg(REG_ADC, SKIP_DCFIL); 314 uda1380_write_reg(REG_ADC, SKIP_DCFIL);
270} 315}
271 316
@@ -373,20 +418,3 @@ void uda1380_set_monitor(int enable)
373 else /* mute channel 2 */ 418 else /* mute channel 2 */
374 uda1380_write_reg(REG_MUTE, uda1380_regs[REG_MUTE] | MUTE_CH2); 419 uda1380_write_reg(REG_MUTE, uda1380_regs[REG_MUTE] | MUTE_CH2);
375} 420}
376
377/* Change the order of the noise chaper,
378 5th order is recommended above 32kHz */
379void uda1380_set_nsorder(int order)
380{
381 switch(order)
382 {
383 case 5:
384 uda1380_write_reg(REG_MIX_CTL, uda1380_regs[REG_MIX_CTL]
385 | MIX_CTL_SEL_NS);
386 break;
387 case 3:
388 default:
389 uda1380_write_reg(REG_MIX_CTL, uda1380_regs[REG_MIX_CTL]
390 & ~MIX_CTL_SEL_NS);
391 }
392}
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index 9099cb3765..d3f544de94 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -20,6 +20,20 @@
20#define AUDIO_H 20#define AUDIO_H
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23#include <sys/types.h>
24/* These must always be included with audio.h for this to compile under
25 cetain conditions. Do it here or else spread the complication around to
26 many files. */
27#if CONFIG_CODEC == SWCODEC
28#include "pcm_sampr.h"
29#include "pcm_playback.h"
30#ifdef HAVE_RECORDING
31#include "pcm_record.h"
32#include "id3.h"
33#include "enc_base.h"
34#endif /* HAVE_RECORDING */
35#endif /* CONFIG_CODEC == SWCODEC */
36
23 37
24#ifdef SIMULATOR 38#ifdef SIMULATOR
25#define audio_play(x) sim_audio_play(x) 39#define audio_play(x) sim_audio_play(x)
@@ -31,9 +45,6 @@
31#define AUDIO_STATUS_PRERECORD 8 45#define AUDIO_STATUS_PRERECORD 8
32#define AUDIO_STATUS_ERROR 16 46#define AUDIO_STATUS_ERROR 16
33 47
34#define AUDIO_STATUS_STAYON_FLAGS \
35 (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE | AUDIO_STATUS_RECORD | AUDIO_)
36
37#define AUDIOERR_DISK_FULL 1 48#define AUDIOERR_DISK_FULL 1
38 49
39#define AUDIO_GAIN_LINEIN 0 50#define AUDIO_GAIN_LINEIN 0
@@ -72,10 +83,11 @@ void audio_resume(void);
72void audio_next(void); 83void audio_next(void);
73void audio_prev(void); 84void audio_prev(void);
74int audio_status(void); 85int audio_status(void);
75bool audio_query_poweroff(void); 86#if CONFIG_CODEC == SWCODEC
76int audio_track_count(void); /* SWCODEC only */ 87int audio_track_count(void); /* SWCODEC only */
77long audio_filebufused(void); /* SWCODEC only */ 88long audio_filebufused(void); /* SWCODEC only */
78void audio_pre_ff_rewind(void); /* SWCODEC only */ 89void audio_pre_ff_rewind(void); /* SWCODEC only */
90#endif /* CONFIG_CODEC == SWCODEC */
79void audio_ff_rewind(long newtime); 91void audio_ff_rewind(long newtime);
80void audio_flush_and_reload_tracks(void); 92void audio_flush_and_reload_tracks(void);
81struct mp3entry* audio_current_track(void); 93struct mp3entry* audio_current_track(void);
@@ -89,18 +101,28 @@ void audio_error_clear(void);
89int audio_get_file_pos(void); 101int audio_get_file_pos(void);
90void audio_beep(int duration); 102void audio_beep(int duration);
91void audio_init_playback(void); 103void audio_init_playback(void);
104unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size);
92 105
93/* audio recording functions */ 106/* channel modes */
94void audio_init_recording(unsigned int buffer_offset); 107enum rec_channel_modes
95void audio_close_recording(void); 108{
96void audio_record(const char *filename); 109 __CHN_MODE_START_INDEX = -1,
97void audio_stop_recording(void); 110
98void audio_pause_recording(void); 111 CHN_MODE_STEREO,
99void audio_resume_recording(void); 112 CHN_MODE_MONO,
100void audio_new_file(const char *filename); 113
114 CHN_NUM_MODES
115};
116
117#if CONFIG_CODEC == SWCODEC
118/* channel mode capability bits */
119#define CHN_CAP_STEREO (1 << CHN_MODE_STEREO)
120#define CHN_CAP_MONO (1 << CHN_MODE_MONO)
121#define CHN_CAP_ALL (CHN_CAP_STEREO | CHN_CAP_MONO)
122#endif /* CONFIG_CODEC == SWCODEC */
101 123
102/* audio sources */ 124/* audio sources */
103enum 125enum audio_sources
104{ 126{
105 AUDIO_SRC_PLAYBACK = -1, /* for audio playback (default) */ 127 AUDIO_SRC_PLAYBACK = -1, /* for audio playback (default) */
106 AUDIO_SRC_MIC, /* monitor mic */ 128 AUDIO_SRC_MIC, /* monitor mic */
@@ -123,33 +145,57 @@ enum
123 AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1 145 AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1
124}; 146};
125 147
126/* channel modes */ 148#ifdef HAVE_RECORDING
127enum 149/* parameters for audio_set_recording_options */
150struct audio_recording_options
128{ 151{
129 CHN_MODE_MONO = 1, 152 int rec_source;
130 CHN_MODE_STEREO, 153 int rec_frequency;
154 int rec_channels;
155 int rec_prerecord_time;
156#if CONFIG_CODEC == SWCODEC
157 int rec_source_flags; /* for rec_set_source */
158 struct encoder_config enc_config;
159#else
160 int rec_quality;
161 bool rec_editable;
162#endif
131}; 163};
132void audio_set_recording_options(int frequency, int quality, 164
133 int source, int channel_mode, 165/* audio recording functions */
134 bool editable, int prerecord_time); 166void audio_init_recording(unsigned int buffer_offset);
167void audio_close_recording(void);
168void audio_record(const char *filename);
169void audio_stop_recording(void);
170void audio_pause_recording(void);
171void audio_resume_recording(void);
172void audio_new_file(const char *filename);
173void audio_set_recording_options(struct audio_recording_options *options);
135void audio_set_recording_gain(int left, int right, int type); 174void audio_set_recording_gain(int left, int right, int type);
136unsigned long audio_recorded_time(void); 175unsigned long audio_recorded_time(void);
137unsigned long audio_num_recorded_bytes(void); 176unsigned long audio_num_recorded_bytes(void);
138#if 0 177
139#ifdef HAVE_SPDIF_POWER
140void audio_set_spdif_power_setting(bool on);
141#endif
142#endif
143unsigned long audio_get_spdif_sample_rate(void);
144unsigned long audio_prev_elapsed(void);
145#if CONFIG_CODEC == SWCODEC 178#if CONFIG_CODEC == SWCODEC
146/* audio encoder functions (defined in playback.c) */ 179/* SWCODEC recoring functions */
147int audio_get_encoder_id(void); 180/* playback.c */
148void audio_load_encoder(int enc_id); 181bool audio_load_encoder(int afmt);
149void audio_remove_encoder(void); 182void audio_remove_encoder(void);
183unsigned char *audio_get_recording_buffer(size_t *buffer_size);
150#endif /* CONFIG_CODEC == SWCODEC */ 184#endif /* CONFIG_CODEC == SWCODEC */
185#endif /* HAVE_RECORDING */
151 186
187#ifdef HAVE_SPDIF_IN
188#ifdef HAVE_SPDIF_POWER
189void audio_set_spdif_power_setting(bool on);
190bool audio_get_spdif_power_setting(void);
191#endif
192/* returns index into rec_master_sampr_list */
193int audio_get_spdif_sample_rate(void);
194/* > 0: monitor EBUin, 0: Monitor IISrecv, <0: reset only */
195void audio_spdif_set_monitor(int monitor_spdif);
196#endif /* HAVE_SPDIF_IN */
152 197
198unsigned long audio_prev_elapsed(void);
153 199
154 200
155/***********************************************************************/ 201/***********************************************************************/
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index 6f74078e1e..285ab88930 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -84,6 +84,12 @@
84/* define this if you have recording possibility */ 84/* define this if you have recording possibility */
85#define HAVE_RECORDING 1 85#define HAVE_RECORDING 1
86 86
87/* define hardware samples rate caps mask */
88#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
89
90/* define the bitmask of recording sample rates */
91#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
92
87#define HAVE_AGC 93#define HAVE_AGC
88 94
89#ifndef SIMULATOR 95#ifndef SIMULATOR
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index 1476102100..b22ff0eb22 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -77,6 +77,12 @@
77/* define this if you have recording possibility */ 77/* define this if you have recording possibility */
78#define HAVE_RECORDING 1 78#define HAVE_RECORDING 1
79 79
80/* define hardware samples rate caps mask */
81#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
82
83/* define the bitmask of recording sample rates */
84#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
85
80#define HAVE_AGC 86#define HAVE_AGC
81 87
82#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */ 88#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */
diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h
index 31f0f6729f..748635dcb4 100644
--- a/firmware/export/config-h300.h
+++ b/firmware/export/config-h300.h
@@ -72,6 +72,12 @@
72/* define this if you have recording possibility */ 72/* define this if you have recording possibility */
73#define HAVE_RECORDING 1 73#define HAVE_RECORDING 1
74 74
75/* define hardware samples rate caps mask */
76#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
77
78/* define the bitmask of recording sample rates */
79#define REC_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
80
75#define HAVE_AGC 81#define HAVE_AGC
76 82
77#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */ 83#define BATTERY_CAPACITY_DEFAULT 1300 /* default battery capacity */
@@ -157,4 +163,3 @@
157 163
158/* Define this for FM radio input available */ 164/* Define this for FM radio input available */
159#define HAVE_FMRADIO_IN 165#define HAVE_FMRADIO_IN
160
diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h
index 80b010a6b0..d4c904ed23 100644
--- a/firmware/export/config-iaudiox5.h
+++ b/firmware/export/config-iaudiox5.h
@@ -9,6 +9,12 @@
9/* define this if you have recording possibility */ 9/* define this if you have recording possibility */
10#define HAVE_RECORDING 1 10#define HAVE_RECORDING 1
11 11
12/* define the bitmask of hardware sample rates */
13#define HW_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
14
15/* define the bitmask of recording sample rates */
16#define REC_SAMPR_CAPS (SAMPR_CAP_88 | SAMPR_CAP_44 | SAMPR_CAP_22 | SAMPR_CAP_11)
17
12/* define this if you have a bitmap LCD display */ 18/* define this if you have a bitmap LCD display */
13#define HAVE_LCD_BITMAP 1 19#define HAVE_LCD_BITMAP 1
14 20
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 1d07affbfa..dd099e0204 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -24,13 +24,19 @@
24#include "file.h" 24#include "file.h"
25 25
26/* Audio file types. */ 26/* Audio file types. */
27enum { 27enum
28{
28 AFMT_UNKNOWN = 0, /* Unknown file format */ 29 AFMT_UNKNOWN = 0, /* Unknown file format */
29 30
31 /* start formats */
32
30 AFMT_MPA_L1, /* MPEG Audio layer 1 */ 33 AFMT_MPA_L1, /* MPEG Audio layer 1 */
31 AFMT_MPA_L2, /* MPEG Audio layer 2 */ 34 AFMT_MPA_L2, /* MPEG Audio layer 2 */
32 AFMT_MPA_L3, /* MPEG Audio layer 3 */ 35 AFMT_MPA_L3, /* MPEG Audio layer 3 */
33 36
37 AFMT_AIFF, /* Audio Interchange File Format */
38
39#if CONFIG_CODEC == SWCODEC
34 AFMT_PCM_WAV, /* Uncompressed PCM in a WAV file */ 40 AFMT_PCM_WAV, /* Uncompressed PCM in a WAV file */
35 AFMT_OGG_VORBIS, /* Ogg Vorbis */ 41 AFMT_OGG_VORBIS, /* Ogg Vorbis */
36 AFMT_FLAC, /* FLAC */ 42 AFMT_FLAC, /* FLAC */
@@ -40,54 +46,91 @@ enum {
40 AFMT_ALAC, /* Apple Lossless Audio Codec */ 46 AFMT_ALAC, /* Apple Lossless Audio Codec */
41 AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */ 47 AFMT_AAC, /* Advanced Audio Coding (AAC) in M4A container */
42 AFMT_SHN, /* Shorten */ 48 AFMT_SHN, /* Shorten */
43 AFMT_AIFF, /* Audio Interchange File Format */
44 AFMT_SID, /* SID File Format */ 49 AFMT_SID, /* SID File Format */
45 AFMT_ADX, /* ADX */ 50 AFMT_ADX, /* ADX File Format */
51#endif
46 52
47 /* New formats must be added to the end of this list */ 53 /* add new formats at any index above this line to have a sensible order -
54 specified array index inits are used */
55 /* format arrays defined in id3.c */
48 56
49 AFMT_NUM_CODECS, 57 AFMT_NUM_CODECS,
50 58
51#if CONFIG_CODEC == SWCODEC 59#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING)
52 /* masks to decompose parts */ 60 /* masks to decompose parts */
53 CODEC_AFMT_MASK = 0x0fff, 61 CODEC_AFMT_MASK = 0x0fff,
54 CODEC_TYPE_MASK = 0x7000, 62 CODEC_TYPE_MASK = 0x7000,
55 63
56 /* switch for specifying codec type when requesting a filename */ 64 /* switch for specifying codec type when requesting a filename */
57 CODEC_TYPE_DECODER = (0 << 12), /* default */ 65 CODEC_TYPE_DECODER = (0 << 12), /* default */
58 CODEC_TYPE_ENCODER = (1 << 12) 66 CODEC_TYPE_ENCODER = (1 << 12),
59#endif 67#endif /* CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) */
60}; 68};
61 69
62#if CONFIG_CODEC == SWCODEC 70#if CONFIG_CODEC == SWCODEC
63#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \ 71#define CODEC_EXTENSION "codec"
64 { label, codec_fname, codec_enc_fname, enc_ext } 72
65#else 73#ifdef HAVE_RECORDING
66#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \ 74#define ENCODER_SUFFIX "_enc"
67 { label } 75enum rec_format_indexes
68#endif 76{
77 __REC_FORMAT_START_INDEX = -1,
78
79 /* start formats */
80
81 REC_FORMAT_PCM_WAV,
82 REC_FORMAT_WAVPACK,
83 REC_FORMAT_MPA_L3,
84
85 /* add new formats at any index above this line to have a sensible order -
86 specified array index inits are used
87 REC_FORMAT_CFG_NUM_BITS should allocate enough bits to hold the range
88 REC_FORMAT_CFG_VALUE_LIST should be in same order as indexes
89 */
90
91 REC_NUM_FORMATS,
92
93 REC_FORMAT_DEFAULT = REC_FORMAT_PCM_WAV,
94 REC_FORMAT_CFG_NUM_BITS = 2
95};
96
97#define REC_FORMAT_CFG_VAL_LIST "wave,wvpk,mpa3"
98
99/* get REC_FORMAT_* corresponding AFMT_* */
100extern const int rec_format_afmt[REC_NUM_FORMATS];
101/* get AFMT_* corresponding REC_FORMAT_* */
102extern const int afmt_rec_format[AFMT_NUM_CODECS];
103
104#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
105 { label, root_fname, enc_root_fname, ext_list }
106#else /* !HAVE_RECORDING */
107#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
108 { label, root_fname, ext_list }
109#endif /* HAVE_RECORDING */
110#else /* !SWCODEC */
111
112#define AFMT_ENTRY(label, root_fname, enc_root_fname, ext_list) \
113 { label, ext_list }
114#endif /* CONFIG_CODEC == SWCODEC */
69 115
70/* record describing the audio format */ 116/* record describing the audio format */
71struct afmt_entry 117struct afmt_entry
72{ 118{
73#if CONFIG_CODEC == SWCODEC
74 char label[8]; /* format label */ 119 char label[8]; /* format label */
75 char *codec_fn; /* filename of decoder codec */ 120#if CONFIG_CODEC == SWCODEC
76 char *codec_enc_fn; /* filename of encoder codec */ 121 char *codec_root_fn; /* root codec filename (sans _enc and .codec) */
77 char *ext; /* default extension for file (enc only for now) */ 122#ifdef HAVE_RECORDING
78#else 123 char *codec_enc_root_fn; /* filename of encoder codec */
79 char label[4]; 124#endif
80#endif 125#endif
126 char *ext_list; /* double NULL terminated extension
127 list for type with the first as
128 the default for recording */
81}; 129};
82 130
83/* database of labels and codecs. add formats per above enum */ 131/* database of labels and codecs. add formats per above enum */
84extern const struct afmt_entry audio_formats[AFMT_NUM_CODECS]; 132extern const struct afmt_entry audio_formats[AFMT_NUM_CODECS];
85 133
86#if CONFIG_CODEC == SWCODEC
87/* recording quality to AFMT_* */
88extern const int rec_quality_info_afmt[9];
89#endif
90
91struct mp3entry { 134struct mp3entry {
92 char path[MAX_PATH]; 135 char path[MAX_PATH];
93 char* title; 136 char* title;
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index a4cd93969b..9c3e96ba63 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -19,11 +19,23 @@
19#ifndef PCM_PLAYBACK_H 19#ifndef PCM_PLAYBACK_H
20#define PCM_PLAYBACK_H 20#define PCM_PLAYBACK_H
21 21
22#include <sys/types.h>
23
24/* Typedef for registered callback (play and record) */
25typedef void (*pcm_more_callback_type)(unsigned char **start,
26 size_t *size);
27
22void pcm_init(void); 28void pcm_init(void);
29
30/* set the pcm frequency - use values in hw_sampr_list
31 * use -1 for the default frequency
32 */
23void pcm_set_frequency(unsigned int frequency); 33void pcm_set_frequency(unsigned int frequency);
34/* apply settings to hardware immediately */
35void pcm_apply_settings(bool reset);
24 36
25/* This is for playing "raw" PCM data */ 37/* This is for playing "raw" PCM data */
26void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size), 38void pcm_play_data(pcm_more_callback_type get_more,
27 unsigned char* start, size_t size); 39 unsigned char* start, size_t size);
28 40
29void pcm_calculate_peaks(int *left, int *right); 41void pcm_calculate_peaks(int *left, int *right);
@@ -35,4 +47,4 @@ void pcm_play_pause(bool play);
35bool pcm_is_paused(void); 47bool pcm_is_paused(void);
36bool pcm_is_playing(void); 48bool pcm_is_playing(void);
37 49
38#endif 50#endif /* PCM_PLAYBACK_H */
diff --git a/firmware/export/pcm_record.h b/firmware/export/pcm_record.h
index b217335340..c1187a4c6c 100644
--- a/firmware/export/pcm_record.h
+++ b/firmware/export/pcm_record.h
@@ -20,24 +20,44 @@
20#ifndef PCM_RECORD_H 20#ifndef PCM_RECORD_H
21#define PCM_RECORD_H 21#define PCM_RECORD_H
22 22
23void enc_set_parameters(int chunk_size, int num_chunks, 23#define DMA_REC_ERROR_DMA ((size_t)-1)
24 int samp_per_chunk, char *head_ptr, int head_size, 24#ifdef HAVE_SPDIF_IN
25 int enc_id); 25#define DMA_REC_ERROR_SPDIF ((size_t)-2)
26void enc_get_inputs(int *buffer_size, int *channels, int *quality); 26#endif
27unsigned int* enc_alloc_chunk(void); 27/* Use AUDIO_SRC_* enumeration values */
28void enc_free_chunk(void); 28void pcm_set_monitor(int monitor);
29int enc_wavbuf_near_empty(void); 29void pcm_set_rec_source(int source);
30char* enc_get_wav_data(int size); 30
31extern void (*enc_set_header_callback)(void *head_buffer, int head_size, 31/**
32 int num_pcm_samples, bool is_file_header); 32 * RAW pcm data recording
33 * These calls are nescessary only when using the raw pcm apis directly.
34 */
35
36/* Initialize pcm recording interface */
37void pcm_init_recording(void);
38/* Uninitialze pcm recording interface */
39void pcm_close_recording(void);
40
41/* Start recording "raw" PCM data */
42void pcm_record_data(pcm_more_callback_type more_ready,
43 unsigned char *start, size_t size);
33 44
45/* Stop tranferring data into supplied buffer */
46void pcm_stop_recording(void);
47
48void pcm_calculate_rec_peaks(int *left, int *right);
49
50/** General functions for high level codec recording **/
51void pcm_rec_error_clear(void);
34unsigned long pcm_rec_status(void); 52unsigned long pcm_rec_status(void);
35void pcm_rec_init(void); 53void pcm_rec_init(void);
36void pcm_rec_mux(int source); 54void pcm_rec_mux(int source);
37int pcm_rec_current_bitrate(void); 55int pcm_rec_current_bitrate(void);
56int pcm_rec_encoder_afmt(void); /* AFMT_* value, AFMT_UNKNOWN if none */
57int pcm_rec_rec_format(void); /* Format index or -1 otherwise */
58unsigned long pcm_rec_sample_rate(void);
38int pcm_get_num_unprocessed(void); 59int pcm_get_num_unprocessed(void);
39void pcm_rec_get_peaks(int *left, int *right);
40 60
41/* audio.h contains audio recording functions */ 61/* audio.h contains audio_* recording functions */
42 62
43#endif 63#endif /* PCM_RECORD_H */
diff --git a/firmware/export/system.h b/firmware/export/system.h
index 4a33d80466..9b90a6e80c 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -21,7 +21,6 @@
21#define __SYSTEM_H__ 21#define __SYSTEM_H__
22 22
23#include "cpu.h" 23#include "cpu.h"
24#include "config.h"
25#include "stdbool.h" 24#include "stdbool.h"
26 25
27extern void system_reboot (void); 26extern void system_reboot (void);
@@ -111,6 +110,23 @@ const char *get_cpu_boost_tracker(void);
111#define MAX(a, b) (((a)>(b))?(a):(b)) 110#define MAX(a, b) (((a)>(b))?(a):(b))
112#endif 111#endif
113 112
113/* return number of elements in array a */
114#define ARRAYLEN(a) (sizeof(a)/sizeof((a)[0]))
115
116/* return p incremented by specified number of bytes */
117#define SKIPBYTES(p, count) ((typeof (p))((char *)(p) + (count)))
118
119#define P2_M1(p2) ((1 << (p2))-1)
120
121/* align up or down to nearest 2^p2 */
122#define ALIGN_DOWN_P2(n, p2) ((n) & ~P2_M1(p2))
123#define ALIGN_UP_P2(n, p2) ALIGN_DOWN_P2((n) + P2_M1(p2),p2)
124
125/* align up or down to nearest integer multiple of a */
126#define ALIGN_DOWN(n, a) ((n)/(a)*(a))
127#define ALIGN_UP(n, a) ALIGN_DOWN((n)+((a)-1),a)
128
129/* live endianness conversion */
114#ifdef ROCKBOX_LITTLE_ENDIAN 130#ifdef ROCKBOX_LITTLE_ENDIAN
115#define letoh16(x) (x) 131#define letoh16(x) (x)
116#define letoh32(x) (x) 132#define letoh32(x) (x)
@@ -120,6 +136,8 @@ const char *get_cpu_boost_tracker(void);
120#define betoh32(x) swap32(x) 136#define betoh32(x) swap32(x)
121#define htobe16(x) swap16(x) 137#define htobe16(x) swap16(x)
122#define htobe32(x) swap32(x) 138#define htobe32(x) swap32(x)
139#define swap_odd_even_be32(x) (x)
140#define swap_odd_even_le32(x) swap_odd_even32(x)
123#else 141#else
124#define letoh16(x) swap16(x) 142#define letoh16(x) swap16(x)
125#define letoh32(x) swap32(x) 143#define letoh32(x) swap32(x)
@@ -129,6 +147,37 @@ const char *get_cpu_boost_tracker(void);
129#define betoh32(x) (x) 147#define betoh32(x) (x)
130#define htobe16(x) (x) 148#define htobe16(x) (x)
131#define htobe32(x) (x) 149#define htobe32(x) (x)
150#define swap_odd_even_be32(x) swap_odd_even32(x)
151#define swap_odd_even_le32(x) (x)
152#endif
153
154/* static endianness conversion */
155#define SWAP_16(x) ((typeof(x))(unsigned short)(((unsigned short)(x) >> 8) | \
156 ((unsigned short)(x) << 8)))
157
158#define SWAP_32(x) ((typeof(x))(unsigned long)( ((unsigned long)(x) >> 24) | \
159 (((unsigned long)(x) & 0xff0000ul) >> 8) | \
160 (((unsigned long)(x) & 0xff00ul) << 8) | \
161 ((unsigned long)(x) << 24)))
162
163#ifdef ROCKBOX_LITTLE_ENDIAN
164#define LE_TO_H16(x) (x)
165#define LE_TO_H32(x) (x)
166#define H_TO_LE16(x) (x)
167#define H_TO_LE32(x) (x)
168#define BE_TO_H16(x) SWAP_16(x)
169#define BE_TO_H32(x) SWAP_32(x)
170#define H_TO_BE16(x) SWAP_16(x)
171#define H_TO_BE32(x) SWAP_32(x)
172#else
173#define LE_TO_H16(x) SWAP_16(x)
174#define LE_TO_H32(x) SWAP_32(x)
175#define H_TO_LE16(x) SWAP_16(x)
176#define H_TO_LE32(x) SWAP_32(x)
177#define BE_TO_H16(x) (x)
178#define BE_TO_H32(x) (x)
179#define H_TO_BE16(x) (x)
180#define H_TO_BE32(x) (x)
132#endif 181#endif
133 182
134 183
@@ -181,6 +230,7 @@ enum {
181 : /* %0 */ I_CONSTRAINT((char)(mask)), \ 230 : /* %0 */ I_CONSTRAINT((char)(mask)), \
182 /* %1 */ "z"(address-GBR)) 231 /* %1 */ "z"(address-GBR))
183 232
233
184#endif /* CONFIG_CPU == SH7034 */ 234#endif /* CONFIG_CPU == SH7034 */
185 235
186#ifndef SIMULATOR 236#ifndef SIMULATOR
@@ -388,7 +438,20 @@ static inline unsigned long swap32(unsigned long value)
388#define invalidate_icache() 438#define invalidate_icache()
389 439
390#endif 440#endif
391#else 441
442#ifndef CPU_COLDFIRE
443static inline unsigned long swap_odd_even32(unsigned long value)
444{
445 /*
446 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
447 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
448 */
449 unsigned long t = value & 0xff00ff00;
450 return (t >> 8) | ((t ^ value) << 8);
451}
452#endif
453
454#else /* SIMULATOR */
392 455
393static inline unsigned short swap16(unsigned short value) 456static inline unsigned short swap16(unsigned short value)
394 /* 457 /*
@@ -412,8 +475,18 @@ static inline unsigned long swap32(unsigned long value)
412 return (lo << 16) | hi; 475 return (lo << 16) | hi;
413} 476}
414 477
478static inline unsigned long swap_odd_even32(unsigned long value)
479{
480 /*
481 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
482 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
483 */
484 unsigned long t = value & 0xff00ff00;
485 return (t >> 8) | ((t ^ value) << 8);
486}
487
415#define invalidate_icache() 488#define invalidate_icache()
416 489
417#endif 490#endif /* !SIMULATOR */
418 491
419#endif 492#endif /* __SYSTEM_H__ */
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index 17e6e3aa88..72c692ec3b 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -142,7 +142,10 @@ void switch_thread(bool save_context, struct thread_entry **blocked_list);
142void sleep_thread(int ticks); 142void sleep_thread(int ticks);
143void block_thread(struct thread_entry **thread, int timeout); 143void block_thread(struct thread_entry **thread, int timeout);
144void wakeup_thread(struct thread_entry **thread); 144void wakeup_thread(struct thread_entry **thread);
145#ifdef HAVE_PRIORITY_SCHEDULING
145int thread_set_priority(struct thread_entry *thread, int priority); 146int thread_set_priority(struct thread_entry *thread, int priority);
147int thread_get_priority(struct thread_entry *thread);
148#endif
146void init_threads(void); 149void init_threads(void);
147int thread_stack_usage(const struct thread_entry *thread); 150int thread_stack_usage(const struct thread_entry *thread);
148int thread_get_status(const struct thread_entry *thread); 151int thread_get_status(const struct thread_entry *thread);
diff --git a/firmware/export/tlv320.h b/firmware/export/tlv320.h
index dfcbec4373..023ec9d874 100644
--- a/firmware/export/tlv320.h
+++ b/firmware/export/tlv320.h
@@ -24,6 +24,16 @@
24 24
25extern void tlv320_init(void); 25extern void tlv320_init(void);
26extern void tlv320_reset(void); 26extern void tlv320_reset(void);
27/**
28 * Sets internal sample rate for DAC and ADC relative to MCLK
29 * Selection for frequency:
30 * Fs: tlv: with:
31 * 11025: 0 = MCLK/2 MCLK/2 SCLK, LRCK: Audio Clk / 16
32 * 22050: 0 = MCLK/2 MCLK SCLK, LRCK: Audio Clk / 8
33 * 44100: 1 = MCLK MCLK SCLK, LRCK: Audio Clk / 4 (default)
34 * 88200: 2 = MCLK*2 MCLK SCLK, LRCK: Audio Clk / 2
35 */
36extern void tlv320_set_frequency(unsigned fsel);
27extern void tlv320_enable_output(bool enable); 37extern void tlv320_enable_output(bool enable);
28extern void tlv320_set_headphone_vol(int vol_l, int vol_r); 38extern void tlv320_set_headphone_vol(int vol_l, int vol_r);
29extern void tlv320_set_recvol(int left, int right, int type); 39extern void tlv320_set_recvol(int left, int right, int type);
diff --git a/firmware/export/uda1380.h b/firmware/export/uda1380.h
index 9c761c6a7d..639ca8aa5c 100644
--- a/firmware/export/uda1380.h
+++ b/firmware/export/uda1380.h
@@ -28,8 +28,17 @@ extern void uda1380_set_bass(int value);
28extern void uda1380_set_treble(int value); 28extern void uda1380_set_treble(int value);
29extern int uda1380_mute(int mute); 29extern int uda1380_mute(int mute);
30extern void uda1380_close(void); 30extern void uda1380_close(void);
31extern void uda1380_set_nsorder(int order); 31/**
32 32 * Sets frequency settings for DAC and ADC relative to MCLK
33 *
34 * Selection for frequency ranges:
35 * Fs: range: with:
36 * 11025: 0 = 6.25 to 12.5 SCLK, LRCK: Audio Clk / 16
37 * 22050: 1 = 12.5 to 25 SCLK, LRCK: Audio Clk / 8
38 * 44100: 2 = 25 to 50 SCLK, LRCK: Audio Clk / 4 (default)
39 * 88200: 3 = 50 to 100 SCLK, LRCK: Audio Clk / 2
40 */
41extern void uda1380_set_frequency(unsigned fsel);
33extern void uda1380_enable_recording(bool source_mic); 42extern void uda1380_enable_recording(bool source_mic);
34extern void uda1380_disable_recording(void); 43extern void uda1380_disable_recording(void);
35extern void uda1380_set_recvol(int left, int right, int type); 44extern void uda1380_set_recvol(int left, int right, int type);
diff --git a/firmware/id3.c b/firmware/id3.c
index 92f60a2095..7d03c75331 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -44,6 +44,89 @@
44#include "replaygain.h" 44#include "replaygain.h"
45#include "rbunicode.h" 45#include "rbunicode.h"
46 46
47/** Database of audio formats **/
48const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
49{
50 /* Unknown file format */
51 [AFMT_UNKNOWN] =
52 AFMT_ENTRY("???", NULL, NULL, NULL ),
53
54 /* MPEG Audio layer 1 */
55 [AFMT_MPA_L1] =
56 AFMT_ENTRY("MP1", "mpa", NULL, "mp1\0" ),
57 /* MPEG Audio layer 2 */
58 [AFMT_MPA_L2] =
59 AFMT_ENTRY("MP2", "mpa", NULL, "mpa\0mp2\0" ),
60 /* MPEG Audio layer 3 */
61 [AFMT_MPA_L3] =
62 AFMT_ENTRY("MP3", "mpa", "mp3_enc", "mp3\0" ),
63
64 /* Audio Interchange File Format */
65 [AFMT_AIFF] =
66 AFMT_ENTRY("AIFF", "aiff", NULL, "aiff\0aif\0"),
67
68#if CONFIG_CODEC == SWCODEC
69 /* Uncompressed PCM in a WAV file */
70 [AFMT_PCM_WAV] =
71 AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ),
72 /* Ogg Vorbis */
73 [AFMT_OGG_VORBIS] =
74 AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0" ),
75 /* FLAC */
76 [AFMT_FLAC] =
77 AFMT_ENTRY("FLAC", "flac", NULL, "flac\0" ),
78 /* Musepack */
79 [AFMT_MPC] =
80 AFMT_ENTRY("MPC", "mpc", NULL, "mpc\0" ),
81 /* A/52 (aka AC3) audio */
82 [AFMT_A52] =
83 AFMT_ENTRY("AC3", "a52", NULL, "a52\0ac3\0" ),
84 /* WavPack */
85 [AFMT_WAVPACK] =
86 AFMT_ENTRY("WV", "wavpack", "wavpack_enc", "wv\0" ),
87 /* Apple Lossless Audio Codec */
88 [AFMT_ALAC] =
89 AFMT_ENTRY("ALAC", "alac", NULL, "m4a\0" ),
90 /* Advanced Audio Coding in M4A container */
91 [AFMT_AAC] =
92 AFMT_ENTRY("AAC", "aac", NULL, "mp4\0" ),
93 /* Shorten */
94 [AFMT_SHN] =
95 AFMT_ENTRY("SHN", "shorten", NULL, "shn\0" ),
96 /* SID File Format */
97 [AFMT_SID] =
98 AFMT_ENTRY("SID", "sid", NULL, "sid\0" ),
99 /* ADX File Format */
100 [AFMT_ADX] =
101 AFMT_ENTRY("ADX", "adx", NULL, "adx\0" ),
102#endif
103};
104
105#if CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING)
106/* get REC_FORMAT_* corresponding AFMT_* */
107const int rec_format_afmt[REC_NUM_FORMATS] =
108{
109 /* give AFMT_UNKNOWN by default */
110 [0 ... REC_NUM_FORMATS-1] = AFMT_UNKNOWN,
111 /* add new entries below this line */
112 [REC_FORMAT_MPA_L3] = AFMT_MPA_L3,
113 [REC_FORMAT_WAVPACK] = AFMT_WAVPACK,
114 [REC_FORMAT_PCM_WAV] = AFMT_PCM_WAV,
115};
116
117/* get AFMT_* corresponding REC_FORMAT_* */
118const int afmt_rec_format[AFMT_NUM_CODECS] =
119{
120 /* give -1 by default */
121 [0 ... AFMT_NUM_CODECS-1] = -1,
122 /* add new entries below this line */
123 [AFMT_MPA_L3] = REC_FORMAT_MPA_L3,
124 [AFMT_WAVPACK] = REC_FORMAT_WAVPACK,
125 [AFMT_PCM_WAV] = REC_FORMAT_PCM_WAV,
126};
127#endif /* CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING) */
128/****/
129
47#define UNSYNC(b0,b1,b2,b3) (((long)(b0 & 0x7F) << (3*7)) | \ 130#define UNSYNC(b0,b1,b2,b3) (((long)(b0 & 0x7F) << (3*7)) | \
48 ((long)(b1 & 0x7F) << (2*7)) | \ 131 ((long)(b1 & 0x7F) << (2*7)) | \
49 ((long)(b2 & 0x7F) << (1*7)) | \ 132 ((long)(b2 & 0x7F) << (1*7)) | \
@@ -85,61 +168,6 @@ static const char* const genres[] = {
85 "Synthpop" 168 "Synthpop"
86}; 169};
87 170
88/* database of audio formats */
89const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
90{
91 /* Unknown file format */
92 AFMT_ENTRY("???", NULL, NULL, NULL ),
93 /* MPEG Audio layer 1 */
94 AFMT_ENTRY("MP1", "mpa.codec", NULL, NULL ),
95 /* MPEG Audio layer 2 */
96 AFMT_ENTRY("MP2", "mpa.codec", NULL, NULL ),
97 /* MPEG Audio layer 3 */
98 AFMT_ENTRY("MP3", "mpa.codec", "mp3_enc.codec", ".mp3"),
99#if CONFIG_CODEC == SWCODEC
100 /* Uncompressed PCM in a WAV file */
101 AFMT_ENTRY("WAV", "wav.codec", "wav_enc.codec", ".wav"),
102 /* Ogg Vorbis */
103 AFMT_ENTRY("Ogg", "vorbis.codec", NULL, NULL ),
104 /* FLAC */
105 AFMT_ENTRY("FLAC", "flac.codec", NULL, NULL ),
106 /* Musepack */
107 AFMT_ENTRY("MPC", "mpc.codec", NULL, NULL ),
108 /* A/52 (aka AC3) audio */
109 AFMT_ENTRY("AC3", "a52.codec", NULL, NULL ),
110 /* WavPack */
111 AFMT_ENTRY("WV", "wavpack.codec", "wavpack_enc.codec", ".wv" ),
112 /* Apple Lossless Audio Codec */
113 AFMT_ENTRY("ALAC", "alac.codec", NULL, NULL ),
114 /* Advanced Audio Coding in M4A container */
115 AFMT_ENTRY("AAC", "aac.codec", NULL, NULL ),
116 /* Shorten */
117 AFMT_ENTRY("SHN", "shorten.codec", NULL, NULL ),
118 /* Audio Interchange File Format */
119 AFMT_ENTRY("AIFF", "aiff.codec", NULL, NULL ),
120 /* SID File Format */
121 AFMT_ENTRY("SID", "sid.codec", NULL, NULL ),
122 /* ADX File Format */
123 AFMT_ENTRY("ADX", "adx.codec", NULL, NULL ),
124#endif
125};
126
127#if CONFIG_CODEC == SWCODEC
128/* recording quality to AFMT_* */
129const int rec_quality_info_afmt[9] =
130{
131 AFMT_MPA_L3, /* MPEG L3 64 kBit/s */
132 AFMT_MPA_L3, /* MPEG L3 96 kBit/s */
133 AFMT_MPA_L3, /* MPEG L3 128 kBit/s */
134 AFMT_MPA_L3, /* MPEG L3 160 kBit/s */
135 AFMT_MPA_L3, /* MPEG L3 192 kBit/s */
136 AFMT_MPA_L3, /* MPEG L3 224 kBit/s */
137 AFMT_MPA_L3, /* MPEG L3 320 kBit/s */
138 AFMT_WAVPACK, /* WavPack 909 kBit/s */
139 AFMT_PCM_WAV, /* PCM Wav 1411 kBit/s */
140};
141#endif /* SWCODEC */
142
143char* id3_get_genre(const struct mp3entry* id3) 171char* id3_get_genre(const struct mp3entry* id3)
144{ 172{
145 if( id3->genre_string ) 173 if( id3->genre_string )
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index ce1d995461..bb438a3ab4 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -2453,34 +2453,32 @@ static void stop_recording(void)
2453 resume_recording(); 2453 resume_recording();
2454} 2454}
2455 2455
2456void audio_set_recording_options(int frequency, int quality, 2456void audio_set_recording_options(struct audio_recording_options *options)
2457 int source, int channel_mode,
2458 bool editable, int prerecord_time)
2459{ 2457{
2460 bool is_mpeg1; 2458 bool is_mpeg1;
2461 2459
2462 is_mpeg1 = (frequency < 3)?true:false; 2460 is_mpeg1 = (options->rec_frequency < 3)?true:false;
2463 2461
2464 rec_version_index = is_mpeg1?3:2; 2462 rec_version_index = is_mpeg1?3:2;
2465 rec_frequency_index = frequency % 3; 2463 rec_frequency_index = options->rec_frequency % 3;
2466 2464
2467 shadow_encoder_control = (quality << 17) | 2465 shadow_encoder_control = (options->rec_quality << 17) |
2468 (rec_frequency_index << 10) | 2466 (rec_frequency_index << 10) |
2469 ((is_mpeg1?1:0) << 9) | 2467 ((is_mpeg1?1:0) << 9) |
2470 (((channel_mode * 2 + 1) & 3) << 6) | 2468 (((options->rec_channels * 2 + 1) & 3) << 6) |
2471 (1 << 5) /* MS-stereo */ | 2469 (1 << 5) /* MS-stereo */ |
2472 (1 << 2) /* Is an original */; 2470 (1 << 2) /* Is an original */;
2473 mas_writemem(MAS_BANK_D0, MAS_D0_ENCODER_CONTROL, &shadow_encoder_control,1); 2471 mas_writemem(MAS_BANK_D0, MAS_D0_ENCODER_CONTROL, &shadow_encoder_control,1);
2474 2472
2475 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control); 2473 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control);
2476 2474
2477 shadow_soft_mute = editable?4:0; 2475 shadow_soft_mute = options->rec_editable?4:0;
2478 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute,1); 2476 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute,1);
2479 2477
2480 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute); 2478 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute);
2481 2479
2482 shadow_io_control_main = ((1 << 10) | /* Monitoring ON */ 2480 shadow_io_control_main = ((1 << 10) | /* Monitoring ON */
2483 ((source < 2)?1:2) << 8) | /* Input select */ 2481 ((options->rec_source < 2)?1:2) << 8) | /* Input select */
2484 (1 << 5) | /* SDO strobe invert */ 2482 (1 << 5) | /* SDO strobe invert */
2485 ((is_mpeg1?0:1) << 3) | 2483 ((is_mpeg1?0:1) << 3) |
2486 (1 << 2) | /* Inverted SIBC clock signal */ 2484 (1 << 2) | /* Inverted SIBC clock signal */
@@ -2489,7 +2487,7 @@ void audio_set_recording_options(int frequency, int quality,
2489 2487
2490 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main); 2488 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
2491 2489
2492 if(source == AUDIO_SRC_MIC) 2490 if(options->rec_source == AUDIO_SRC_MIC)
2493 { 2491 {
2494 /* Copy left channel to right (mono mode) */ 2492 /* Copy left channel to right (mono mode) */
2495 mas_codec_writereg(8, 0x8000); 2493 mas_codec_writereg(8, 0x8000);
@@ -2500,7 +2498,7 @@ void audio_set_recording_options(int frequency, int quality,
2500 mas_codec_writereg(8, 0); 2498 mas_codec_writereg(8, 0);
2501 } 2499 }
2502 2500
2503 prerecording_max_seconds = prerecord_time; 2501 prerecording_max_seconds = options->rec_prerecord_time;
2504 if(prerecording_max_seconds) 2502 if(prerecording_max_seconds)
2505 { 2503 {
2506 prerecording = true; 2504 prerecording = true;
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index cd14f123d1..b7ea96f3d3 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -16,259 +16,86 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include <stdbool.h> 19#include "system.h"
20#include "config.h" 20#include "kernel.h"
21#include "debug.h" 21#include "logf.h"
22#include "panic.h" 22#include "audio.h"
23#include <kernel.h> 23#if defined(HAVE_WM8975)
24#include "cpu.h"
25#include "i2c.h"
26#if defined(HAVE_UDA1380)
27#include "uda1380.h"
28#elif defined(HAVE_WM8975)
29#include "wm8975.h" 24#include "wm8975.h"
30#elif defined(HAVE_WM8758) 25#elif defined(HAVE_WM8758)
31#include "wm8758.h" 26#include "wm8758.h"
32#elif defined(HAVE_TLV320)
33#include "tlv320.h"
34#elif defined(HAVE_WM8731) || defined(HAVE_WM8721) 27#elif defined(HAVE_WM8731) || defined(HAVE_WM8721)
35#include "wm8731l.h" 28#include "wm8731l.h"
36#elif CONFIG_CPU == PNX0101 29#elif CONFIG_CPU == PNX0101
30#include "string.h"
37#include "pnx0101.h" 31#include "pnx0101.h"
38#endif 32#endif
39#include "system.h"
40#include "logf.h"
41 33
42#include <stdio.h> 34/**
43#include <string.h> 35 * APIs implemented in the target-specific portion:
44#include <stdarg.h> 36 * Public -
45#include "pcm_playback.h" 37 * pcm_init
46#include "lcd.h" 38 * pcm_get_bytes_waiting
47#include "button.h" 39 * pcm_calculate_peaks
48#include "file.h" 40 * Semi-private -
49#include "buffer.h" 41 * pcm_play_dma_start
50#include "sprintf.h" 42 * pcm_play_dma_stop
51#include "button.h" 43 * pcm_play_pause_pause
52#include <string.h> 44 * pcm_play_pause_unpause
53 45 */
54static bool pcm_playing; 46
55static bool pcm_paused; 47/** These items may be implemented target specifically or need to
48 be shared semi-privately **/
56 49
57/* the registered callback function to ask for more mp3 data */ 50/* the registered callback function to ask for more mp3 data */
58static void (*callback_for_more)(unsigned char**, size_t*) IDATA_ATTR = NULL; 51pcm_more_callback_type pcm_callback_for_more = NULL;
52bool pcm_playing = false;
53bool pcm_paused = false;
54
55void pcm_play_dma_start(const void *addr, size_t size);
56void pcm_play_dma_stop(void);
57void pcm_play_pause_pause(void);
58void pcm_play_pause_unpause(void);
59
60/** Functions that require targeted implementation **/
61
62#ifndef CPU_COLDFIRE
59 63
60#if (CONFIG_CPU == S3C2440) 64#if (CONFIG_CPU == S3C2440)
61 65
62/* TODO: Implement for Gigabeat 66/* TODO: Implement for Gigabeat
63 For now, just implement some dummy functions. 67 For now, just implement some dummy functions.
64*/ 68*/
65
66void pcm_init(void) 69void pcm_init(void)
67{ 70{
68
69} 71}
70 72
71static void dma_start(const void *addr, size_t size) 73void pcm_play_dma_start(const void *addr, size_t size)
72{ 74{
73 (void)addr; 75 (void)addr;
74 (void)size; 76 (void)size;
75} 77}
76 78
77void pcm_set_frequency(unsigned int frequency) 79void pcm_play_dma_stop(void)
78{
79 (void)frequency;
80}
81
82void pcm_play_stop(void)
83{ 80{
84} 81}
85 82
86size_t pcm_get_bytes_waiting(void) 83void pcm_play_pause_pause(void)
87{ 84{
88 return 0;
89} 85}
90#else
91#ifdef CPU_COLDFIRE
92 86
93#ifdef HAVE_SPDIF_OUT 87void pcm_play_pause_unpause(void)
94#define EBU_DEFPARM ((7 << 12) | (3 << 8) | (1 << 5) | (5 << 2))
95#endif
96#define IIS_DEFPARM(freq) ((freq << 12) | 0x300 | 4 << 2)
97#define IIS_RESET 0x800
98
99#ifdef IAUDIO_X5
100#define SET_IIS_CONFIG(x) IIS1CONFIG = (x);
101#else
102#define SET_IIS_CONFIG(x) IIS2CONFIG = (x);
103#endif
104
105static int pcm_freq = 0x6; /* 44.1 is default */
106
107int peak_left = 0, peak_right = 0;
108
109/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
110static void dma_start(const void *addr, size_t size)
111{ 88{
112 pcm_playing = true;
113
114 addr = (void *)((unsigned long)addr & ~3); /* Align data */
115 size &= ~3; /* Size must be multiple of 4 */
116
117 /* Reset the audio FIFO */
118#ifdef HAVE_SPDIF_OUT
119 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
120#endif
121
122 /* Set up DMA transfer */
123 SAR0 = (unsigned long)addr; /* Source address */
124 DAR0 = (unsigned long)&PDOR3; /* Destination address */
125 BCR0 = size; /* Bytes to transfer */
126
127 /* Enable the FIFO and force one write to it */
128 SET_IIS_CONFIG(IIS_DEFPARM(pcm_freq));
129 /* Also send the audio to S/PDIF */
130#ifdef HAVE_SPDIF_OUT
131 EBU1CONFIG = EBU_DEFPARM;
132#endif
133 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_SINC | (3 << 20) | DMA_START;
134} 89}
135 90
136/* Stops the DMA transfer and interrupt */
137static void dma_stop(void)
138{
139 pcm_playing = false;
140
141 DCR0 = 0;
142 DSR0 = 1;
143 /* Reset the FIFO */
144 SET_IIS_CONFIG(IIS_RESET | IIS_DEFPARM(pcm_freq));
145#ifdef HAVE_SPDIF_OUT
146 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
147#endif
148}
149
150/* sets frequency of input to DAC */
151void pcm_set_frequency(unsigned int frequency) 91void pcm_set_frequency(unsigned int frequency)
152{ 92{
153 switch(frequency) 93 (void)frequency;
154 {
155 case 11025:
156 pcm_freq = 0x2;
157#ifdef HAVE_UDA1380
158 uda1380_set_nsorder(3);
159#endif
160 break;
161 case 22050:
162 pcm_freq = 0x4;
163#ifdef HAVE_UDA1380
164 uda1380_set_nsorder(3);
165#endif
166 break;
167 case 44100:
168 default:
169 pcm_freq = 0x6;
170#ifdef HAVE_UDA1380
171 uda1380_set_nsorder(5);
172#endif
173 break;
174 }
175} 94}
176 95
177size_t pcm_get_bytes_waiting(void) 96size_t pcm_get_bytes_waiting(void)
178{ 97{
179 return (BCR0 & 0xffffff); 98 return 0;
180}
181
182/* DMA0 Interrupt is called when the DMA has finished transfering a chunk */
183void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
184void DMA0(void)
185{
186 int res = DSR0;
187
188 DSR0 = 1; /* Clear interrupt */
189 DCR0 &= ~DMA_EEXT;
190
191 /* Stop on error */
192 if(res & 0x70)
193 {
194 dma_stop();
195 logf("DMA Error:0x%04x", res);
196 }
197 else
198 {
199 size_t next_size;
200 unsigned char *next_start;
201 {
202 void (*get_more)(unsigned char**, size_t*) = callback_for_more;
203 if (get_more)
204 get_more(&next_start, &next_size);
205 else
206 {
207 next_size = 0;
208 next_start = NULL;
209 }
210 }
211 if(next_size)
212 {
213 SAR0 = (unsigned long)next_start; /* Source address */
214 BCR0 = next_size; /* Bytes to transfer */
215 DCR0 |= DMA_EEXT;
216 }
217 else
218 {
219 /* Finished playing */
220 dma_stop();
221 logf("DMA No Data:0x%04x", res);
222 }
223 }
224
225 IPR |= (1<<14); /* Clear pending interrupt request */
226}
227
228void pcm_init(void)
229{
230 pcm_playing = false;
231 pcm_paused = false;
232
233 MPARK = 0x81; /* PARK[1,0]=10 + BCR24BIT */
234 DIVR0 = 54; /* DMA0 is mapped into vector 54 in system.c */
235 DMAROUTE = (DMAROUTE & 0xffffff00) | DMA0_REQ_AUDIO_1;
236 DMACONFIG = 1; /* DMA0Req = PDOR3 */
237
238 /* Reset the audio FIFO */
239 SET_IIS_CONFIG(IIS_RESET);
240
241 /* Enable interrupt at level 7, priority 0 */
242 ICR6 = 0x1c;
243 IMR &= ~(1<<14); /* bit 14 is DMA0 */
244
245 pcm_set_frequency(44100);
246
247 /* Prevent pops (resets DAC to zero point) */
248 SET_IIS_CONFIG(IIS_DEFPARM(pcm_freq) | IIS_RESET);
249
250#if defined(HAVE_UDA1380)
251 /* Initialize default register values. */
252 uda1380_init();
253
254 /* Sleep a while so the power can stabilize (especially a long
255 delay is needed for the line out connector). */
256 sleep(HZ);
257
258 /* Power on FSDAC and HP amp. */
259 uda1380_enable_output(true);
260
261 /* Unmute the master channel (DAC should be at zero point now). */
262 uda1380_mute(false);
263
264#elif defined(HAVE_TLV320)
265 tlv320_init();
266 sleep(HZ/4);
267 tlv320_mute(false);
268#endif
269
270 /* Call dma_stop to initialize everything. */
271 dma_stop();
272} 99}
273 100
274#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \ 101#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
@@ -286,14 +113,14 @@ void pcm_init(void)
286#define FIFO_FREE_COUNT 4 /* TODO: make this sensible */ 113#define FIFO_FREE_COUNT 4 /* TODO: make this sensible */
287#endif 114#endif
288 115
289static int pcm_freq = 44100; /* 44.1 is default */ 116static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
290 117
291/* NOTE: The order of these two variables is important if you use the iPod 118/* NOTE: The order of these two variables is important if you use the iPod
292 assembler optimised fiq handler, so don't change it. */ 119 assembler optimised fiq handler, so don't change it. */
293unsigned short* p IBSS_ATTR; 120unsigned short* p IBSS_ATTR;
294size_t p_size IBSS_ATTR; 121size_t p_size IBSS_ATTR;
295 122
296static void dma_start(const void *addr, size_t size) 123void pcm_play_dma_start(const void *addr, size_t size)
297{ 124{
298 p=(unsigned short*)addr; 125 p=(unsigned short*)addr;
299 p_size=size; 126 p_size=size;
@@ -341,7 +168,7 @@ static void dma_start(const void *addr, size_t size)
341} 168}
342 169
343/* Stops the DMA transfer and interrupt */ 170/* Stops the DMA transfer and interrupt */
344static void dma_stop(void) 171void pcm_play_dma_stop(void)
345{ 172{
346 pcm_playing = false; 173 pcm_playing = false;
347 174
@@ -365,9 +192,58 @@ static void dma_stop(void)
365 disable_fiq(); 192 disable_fiq();
366} 193}
367 194
195void pcm_play_pause_pause(void)
196{
197#if CONFIG_CPU == PP5020
198 /* Disable the interrupt */
199 IISCONFIG &= ~0x2;
200 /* Disable playback FIFO */
201 IISCONFIG &= ~0x20000000;
202#elif CONFIG_CPU == PP5002
203 /* Disable the interrupt */
204 IISFIFO_CFG &= ~(1<<9);
205 /* Disable playback FIFO */
206 IISCONFIG &= ~0x4;
207#endif
208 disable_fiq();
209}
210
211void pcm_play_pause_unpause(void)
212{
213 /* Enable the FIFO and fill it */
214
215 enable_fiq();
216
217 /* Enable playback FIFO */
218#if CONFIG_CPU == PP5020
219 IISCONFIG |= 0x20000000;
220#elif CONFIG_CPU == PP5002
221 IISCONFIG |= 0x4;
222#endif
223
224 /* Fill the FIFO - we assume there are enough bytes in the
225 pcm buffer to fill the 32-byte FIFO. */
226 while (p_size > 0) {
227 if (FIFO_FREE_COUNT < 2) {
228 /* Enable interrupt */
229#if CONFIG_CPU == PP5020
230 IISCONFIG |= 0x2;
231#elif CONFIG_CPU == PP5002
232 IISFIFO_CFG |= (1<<9);
233#endif
234 return;
235 }
236
237 IISFIFO_WR = (*(p++))<<16;
238 IISFIFO_WR = (*(p++))<<16;
239 p_size-=4;
240 }
241}
242
368void pcm_set_frequency(unsigned int frequency) 243void pcm_set_frequency(unsigned int frequency)
369{ 244{
370 pcm_freq=frequency; 245 (void)frequency;
246 pcm_freq = HW_SAMPR_DEFAULT;
371} 247}
372 248
373size_t pcm_get_bytes_waiting(void) 249size_t pcm_get_bytes_waiting(void)
@@ -378,8 +254,8 @@ size_t pcm_get_bytes_waiting(void)
378/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode 254/* ASM optimised FIQ handler. GCC fails to make use of the fact that FIQ mode
379 has registers r8-r14 banked, and so does not need to be saved. This routine 255 has registers r8-r14 banked, and so does not need to be saved. This routine
380 uses only these registers, and so will never touch the stack unless it 256 uses only these registers, and so will never touch the stack unless it
381 actually needs to do so when calling callback_for_more. C version is still 257 actually needs to do so when calling pcm_callback_for_more. C version is
382 included below for reference. 258 still included below for reference.
383 */ 259 */
384#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 260#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
385void fiq(void) ICODE_ATTR __attribute__((naked)); 261void fiq(void) ICODE_ATTR __attribute__((naked));
@@ -433,10 +309,10 @@ void fiq(void)
433 "add r1, r11, #4 \n\t" /* r1 = &p_size */ 309 "add r1, r11, #4 \n\t" /* r1 = &p_size */
434 "str r9, [r0] \n\t" /* save internal copies of variables back */ 310 "str r9, [r0] \n\t" /* save internal copies of variables back */
435 "str r8, [r1] \n\t" 311 "str r8, [r1] \n\t"
436 "ldr r2, =callback_for_more\n\t" 312 "ldr r2, =pcm_callback_for_more\n\t"
437 "ldr r2, [r2] \n\t" /* get callback address */ 313 "ldr r2, [r2] \n\t" /* get callback address */
438 "cmp r2, #0 \n\t" /* check for null pointer */ 314 "cmp r2, #0 \n\t" /* check for null pointer */
439 "movne lr, pc \n\t" /* call callback_for_more */ 315 "movne lr, pc \n\t" /* call pcm_callback_for_more */
440 "bxne r2 \n\t" 316 "bxne r2 \n\t"
441 "ldmia sp!, { r0-r3, r12, lr}\n\t" 317 "ldmia sp!, { r0-r3, r12, lr}\n\t"
442 "ldr r8, [r11, #4] \n\t" /* reload p_size and p */ 318 "ldr r8, [r11, #4] \n\t" /* reload p_size and p */
@@ -477,7 +353,7 @@ void fiq(void)
477 "b .exit \n\t" 353 "b .exit \n\t"
478 ); 354 );
479} 355}
480#else 356#else /* !(CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002) */
481void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); 357void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ")));
482void fiq(void) 358void fiq(void)
483{ 359{
@@ -507,20 +383,21 @@ void fiq(void)
507 } 383 }
508 384
509 /* p is empty, get some more data */ 385 /* p is empty, get some more data */
510 if (callback_for_more) { 386 if (pcm_callback_for_more) {
511 callback_for_more((unsigned char**)&p,&p_size); 387 pcm_callback_for_more((unsigned char**)&p,&p_size);
512 } 388 }
513 } while (p_size); 389 } while (p_size);
514 390
515 /* No more data, so disable the FIFO/FIQ */ 391 /* No more data, so disable the FIFO/FIQ */
516 dma_stop(); 392 pcm_play_dma_stop();
517} 393}
518#endif 394#endif /* CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 */
519 395
520void pcm_init(void) 396void pcm_init(void)
521{ 397{
522 pcm_playing = false; 398 pcm_playing = false;
523 pcm_paused = false; 399 pcm_paused = false;
400 pcm_callback_for_more = NULL;
524 401
525 /* Initialize default register values. */ 402 /* Initialize default register values. */
526 wmcodec_init(); 403 wmcodec_init();
@@ -531,8 +408,8 @@ void pcm_init(void)
531 /* Unmute the master channel (DAC should be at zero point now). */ 408 /* Unmute the master channel (DAC should be at zero point now). */
532 wmcodec_mute(false); 409 wmcodec_mute(false);
533 410
534 /* Call dma_stop to initialize everything. */ 411 /* Call pcm_play_dma_stop to initialize everything. */
535 dma_stop(); 412 pcm_play_dma_stop();
536} 413}
537 414
538#elif (CONFIG_CPU == PNX0101) 415#elif (CONFIG_CPU == PNX0101)
@@ -542,12 +419,16 @@ void pcm_init(void)
542short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES]; 419short __attribute__((section(".dmabuf"))) dma_buf_left[DMA_BUF_SAMPLES];
543short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES]; 420short __attribute__((section(".dmabuf"))) dma_buf_right[DMA_BUF_SAMPLES];
544 421
545static int pcm_freq = 44100; /* 44.1 is default */ 422static int pcm_freq = HW_SAMPR_DEFAULT; /* 44.1 is default */
546 423
547unsigned short* p IBSS_ATTR; 424unsigned short* p IBSS_ATTR;
548size_t p_size IBSS_ATTR; 425size_t p_size IBSS_ATTR;
549 426
550static void dma_start(const void *addr, size_t size) 427void pcm_init(void)
428{
429}
430
431void pcm_play_dma_start(const void *addr, size_t size)
551{ 432{
552 p = (unsigned short*)addr; 433 p = (unsigned short*)addr;
553 p_size = size; 434 p_size = size;
@@ -555,11 +436,19 @@ static void dma_start(const void *addr, size_t size)
555 pcm_playing = true; 436 pcm_playing = true;
556} 437}
557 438
558static void dma_stop(void) 439void pcm_play_dma_stop(void)
559{ 440{
560 pcm_playing = false; 441 pcm_playing = false;
561} 442}
562 443
444void pcm_play_pause_pause(void)
445{
446}
447
448void pcm_play_pause_unpause(void)
449{
450}
451
563static inline void fill_dma_buf(int offset) 452static inline void fill_dma_buf(int offset)
564{ 453{
565 short *l, *r, *lend; 454 short *l, *r, *lend;
@@ -611,8 +500,8 @@ static inline void fill_dma_buf(int offset)
611 p = tmp_p; 500 p = tmp_p;
612 if (l >= lend) 501 if (l >= lend)
613 return; 502 return;
614 else if (callback_for_more) 503 else if (pcm_callback_for_more)
615 callback_for_more((unsigned char**)&p, 504 pcm_callback_for_more((unsigned char**)&p,
616 &p_size); 505 &p_size);
617 } 506 }
618 while (p_size); 507 while (p_size);
@@ -647,9 +536,10 @@ unsigned long physical_address(void *p)
647void pcm_init(void) 536void pcm_init(void)
648{ 537{
649 int i; 538 int i;
650 callback_for_more = NULL; 539
651 pcm_playing = false; 540 pcm_playing = false;
652 pcm_paused = false; 541 pcm_paused = false;
542 pcm_callback_for_more = NULL;
653 543
654 memset(dma_buf_left, 0, sizeof(dma_buf_left)); 544 memset(dma_buf_left, 0, sizeof(dma_buf_left));
655 memset(dma_buf_right, 0, sizeof(dma_buf_right)); 545 memset(dma_buf_right, 0, sizeof(dma_buf_right));
@@ -691,271 +581,37 @@ void pcm_init(void)
691 581
692void pcm_set_frequency(unsigned int frequency) 582void pcm_set_frequency(unsigned int frequency)
693{ 583{
694 pcm_freq=frequency; 584 (void)frequency;
585 pcm_freq = HW_SAMPR_DEFAULT;
695} 586}
696size_t pcm_get_bytes_waiting(void) 587size_t pcm_get_bytes_waiting(void)
697{ 588{
698 return p_size; 589 return p_size;
699} 590}
700#endif 591#endif /* CONFIG_CPU == */
701 592
702void pcm_play_stop(void) 593/* dummy functions for those not actually supporting all this yet */
594void pcm_apply_settings(bool reset)
703{ 595{
704 if (pcm_playing) { 596 (void)reset;
705 dma_stop();
706 }
707} 597}
708 598
709#endif 599void pcm_set_monitor(int monitor)
710
711void pcm_play_data(void (*get_more)(unsigned char** start, size_t* size),
712 unsigned char* start, size_t size)
713{ 600{
714 callback_for_more = get_more; 601 (void)monitor;
715
716 if (!(start && size))
717 {
718 if (get_more)
719 get_more(&start, &size);
720 else
721 return;
722 }
723 if (start && size)
724 {
725 dma_start(start, size);
726 if (pcm_paused) {
727 pcm_paused = false;
728 pcm_play_pause(false);
729 }
730 }
731} 602}
603/** **/
732 604
733void pcm_mute(bool mute) 605void pcm_mute(bool mute)
734{ 606{
735#ifdef HAVE_UDA1380 607#if defined(HAVE_WM8975) || defined(HAVE_WM8758) \
736 uda1380_mute(mute);
737#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
738 || defined(HAVE_WM8731) || defined(HAVE_WM8721) 608 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
739 wmcodec_mute(mute); 609 wmcodec_mute(mute);
740#elif defined(HAVE_TLV320)
741 tlv320_mute(mute);
742#endif 610#endif
743 if (mute) 611 if (mute)
744 sleep(HZ/16); 612 sleep(HZ/16);
745} 613}
746 614
747void pcm_play_pause(bool play)
748{
749 bool needs_change = pcm_paused == play;
750
751 /* This needs to be done ahead of the rest to prevent infinite
752 * recursion from dma_start */
753 pcm_paused = !play;
754 if (pcm_playing && needs_change) {
755 if(play) {
756 if (pcm_get_bytes_waiting()) {
757 logf("unpause");
758
759#ifdef CPU_COLDFIRE
760 /* Enable the FIFO and force one write to it */
761 SET_IIS_CONFIG(IIS_DEFPARM(pcm_freq));
762#ifdef HAVE_SPDIF_OUT
763 EBU1CONFIG = EBU_DEFPARM;
764#endif
765 DCR0 |= DMA_EEXT | DMA_START;
766#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
767 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
768 /* Enable the FIFO and fill it */
769
770 enable_fiq();
771
772 /* Enable playback FIFO */
773#if CONFIG_CPU == PP5020
774 IISCONFIG |= 0x20000000;
775#elif CONFIG_CPU == PP5002
776 IISCONFIG |= 0x4;
777#endif
778
779 /* Fill the FIFO - we assume there are enough bytes in the
780 pcm buffer to fill the 32-byte FIFO. */
781 while (p_size > 0) {
782 if (FIFO_FREE_COUNT < 2) {
783 /* Enable interrupt */
784#if CONFIG_CPU == PP5020
785 IISCONFIG |= 0x2;
786#elif CONFIG_CPU == PP5002
787 IISFIFO_CFG |= (1<<9);
788#endif
789 return;
790 }
791
792 IISFIFO_WR = (*(p++))<<16;
793 IISFIFO_WR = (*(p++))<<16;
794 p_size-=4;
795 }
796#elif (CONFIG_CPU == PNX0101 || CONFIG_CPU == S3C2440) /* End wmcodecs */
797 /* nothing yet */
798#endif
799 } else {
800#if (CONFIG_CPU != PNX0101 && CONFIG_CPU != S3C2440)
801 size_t next_size;
802 unsigned char *next_start;
803 void (*get_more)(unsigned char**, size_t*) = callback_for_more;
804 logf("unpause, no data waiting");
805 if (get_more)
806 get_more(&next_start, &next_size);
807 if (next_start && next_size)
808 dma_start(next_start, next_size);
809 else
810 {
811 dma_stop();
812 logf("unpause attempted, no data");
813 }
814#endif
815 }
816 } else {
817 logf("pause");
818
819#ifdef CPU_COLDFIRE
820 /* Disable DMA peripheral request. */
821 DCR0 &= ~DMA_EEXT;
822 SET_IIS_CONFIG(IIS_RESET | IIS_DEFPARM(pcm_freq));
823#ifdef HAVE_SPDIF_OUT
824 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
825#endif
826#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
827 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
828#if CONFIG_CPU == PP5020
829 /* Disable the interrupt */
830 IISCONFIG &= ~0x2;
831 /* Disable playback FIFO */
832 IISCONFIG &= ~0x20000000;
833#elif CONFIG_CPU == PP5002
834 /* Disable the interrupt */
835 IISFIFO_CFG &= ~(1<<9);
836 /* Disable playback FIFO */
837 IISCONFIG &= ~0x4;
838#endif
839
840 disable_fiq();
841#elif (CONFIG_CPU == PNX0101 || CONFIG_CPU == S3C2440) /* End wmcodecs */
842 /* nothing yet */
843#endif
844 }
845 } /* pcm_playing && needs_change */
846}
847
848bool pcm_is_playing(void) {
849 return pcm_playing;
850}
851
852bool pcm_is_paused(void) {
853 return pcm_paused;
854}
855
856
857#if defined(CPU_COLDFIRE)
858/* Peaks ahead in the DMA buffer based upon the calling period to
859 attempt to compensate for the delay. Keeps a moving average of
860 length four. */
861void pcm_calculate_peaks(int *left, int *right)
862{
863 unsigned long samples;
864 unsigned long *addr, *end;
865 long peak_p, peak_n;
866
867 static unsigned long last_peak_tick = 0;
868 static unsigned long frame_period = 0;
869
870 /* Throttled peak ahead based on calling period */
871 unsigned long period = current_tick - last_peak_tick;
872
873 /* Keep reasonable limits on period */
874 if (period < 1)
875 period = 1;
876 else if (period > HZ/5)
877 period = HZ/5;
878
879 frame_period = (3*frame_period + period) >> 2;
880
881 last_peak_tick = current_tick;
882
883 if (!pcm_playing || pcm_paused)
884 {
885 peak_left = peak_right = 0;
886 goto peak_done;
887 }
888
889 samples = (BCR0 & 0xffffff) >> 2;
890 addr = (long *)(SAR0 & ~3);
891 samples = MIN(frame_period*44100/HZ, samples);
892 end = addr + samples;
893 peak_p = peak_n = 0;
894
895 if (left && right)
896 {
897 if (samples > 0)
898 {
899 long peak_rp = 0, peak_rn = 0;
900
901 do
902 {
903 long value = *addr;
904 long ch;
905
906 ch = value >> 16;
907 if (ch > peak_p) peak_p = ch;
908 else if (ch < peak_n) peak_n = ch;
909
910 ch = (short)value;
911 if (ch > peak_rp) peak_rp = ch;
912 else if (ch < peak_rn) peak_rn = ch;
913
914 addr += 4;
915 }
916 while (addr < end);
917
918 peak_left = MAX(peak_p, -peak_n);
919 peak_right = MAX(peak_rp, -peak_rn);
920 }
921 }
922 else if (left || right)
923 {
924 if (samples > 0)
925 {
926 if (left)
927 {
928 /* Put left channel in low word */
929 addr = (long *)((short *)addr - 1);
930 end = (long *)((short *)end - 1);
931 }
932
933 do
934 {
935 long value = *(short *)addr;
936
937 if (value > peak_p) peak_p = value;
938 else if (value < peak_n) peak_n = value;
939
940 addr += 4;
941 }
942 while (addr < end);
943
944 if (left)
945 peak_left = MAX(peak_p, -peak_n);
946 else
947 peak_right = MAX(peak_p, -peak_n);
948 }
949 }
950
951peak_done:
952 if (left)
953 *left = peak_left;
954
955 if (right)
956 *right = peak_right;
957}
958#else
959/* 615/*
960 * This function goes directly into the DMA buffer to calculate the left and 616 * This function goes directly into the DMA buffer to calculate the left and
961 * right peak values. To avoid missing peaks it tries to look forward two full 617 * right peak values. To avoid missing peaks it tries to look forward two full
@@ -1037,4 +693,94 @@ void pcm_calculate_peaks(int *left, int *right)
1037 } 693 }
1038#endif 694#endif
1039} 695}
696
1040#endif /* CPU_COLDFIRE */ 697#endif /* CPU_COLDFIRE */
698
699/****************************************************************************
700 * Functions that do not require targeted implementation but only a targeted
701 * interface
702 */
703
704/* Common code to pcm_play_data and pcm_play_pause
705 Returns true if DMA playback was started, else false. */
706bool pcm_play_data_start(pcm_more_callback_type get_more,
707 unsigned char *start, size_t size)
708{
709 if (!(start && size))
710 {
711 size = 0;
712 if (get_more)
713 get_more(&start, &size);
714 }
715
716 if (start && size)
717 {
718 pcm_play_dma_start(start, size);
719 return true;
720 }
721
722 return false;
723}
724
725void pcm_play_data(pcm_more_callback_type get_more,
726 unsigned char *start, size_t size)
727{
728 pcm_callback_for_more = get_more;
729
730 if (pcm_play_data_start(get_more, start, size) && pcm_paused)
731 {
732 pcm_paused = false;
733 pcm_play_pause(false);
734 }
735}
736
737void pcm_play_pause(bool play)
738{
739 bool needs_change = pcm_paused == play;
740
741 /* This needs to be done ahead of the rest to prevent infinite
742 recursion from pcm_play_data */
743 pcm_paused = !play;
744
745 if (pcm_playing && needs_change)
746 {
747 if (play)
748 {
749 if (pcm_get_bytes_waiting())
750 {
751 logf("unpause");
752 pcm_play_pause_unpause();
753 }
754 else
755 {
756 logf("unpause, no data waiting");
757 if (!pcm_play_data_start(pcm_callback_for_more, NULL, 0))
758 {
759 pcm_play_dma_stop();
760 logf("unpause attempted, no data");
761 }
762 }
763 }
764 else
765 {
766 logf("pause");
767 pcm_play_pause_pause();
768 }
769 } /* pcm_playing && needs_change */
770}
771
772void pcm_play_stop(void)
773{
774 if (pcm_playing)
775 pcm_play_dma_stop();
776}
777
778bool pcm_is_playing(void)
779{
780 return pcm_playing;
781}
782
783bool pcm_is_paused(void)
784{
785 return pcm_paused;
786}
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index 2785d4b1b1..25f1f1ef64 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -16,199 +16,238 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19 19#include "system.h"
20#include "config.h" 20#include "kernel.h"
21#include "debug.h" 21#include "logf.h"
22#include "panic.h" 22#include "panic.h"
23#include "thread.h" 23#include "thread.h"
24
25#include <kernel.h>
26#include <stdio.h>
27#include <string.h>
28#include <stdarg.h>
29#include <string.h> 24#include <string.h>
30 25#include "ata.h"
31#include "cpu.h" 26#include "usb.h"
32#include "i2c.h" 27#if defined(HAVE_UDA1380)
33#include "power.h"
34#ifdef HAVE_UDA1380
35#include "uda1380.h" 28#include "uda1380.h"
36#endif 29#include "general.h"
37#ifdef HAVE_TLV320 30#elif defined(HAVE_TLV320)
38#include "tlv320.h" 31#include "tlv320.h"
39#endif 32#endif
40#include "system.h"
41#include "usb.h"
42
43#include "buffer.h" 33#include "buffer.h"
44#include "audio.h" 34#include "audio.h"
45#include "button.h"
46#include "file.h"
47#include "sprintf.h"
48#include "logf.h"
49#include "button.h"
50#include "lcd.h"
51#include "lcd-remote.h"
52#include "pcm_playback.h"
53#include "sound.h" 35#include "sound.h"
54#include "id3.h" 36#include "id3.h"
55#include "pcm_record.h"
56
57extern int boost_counter; /* used for boost check */
58 37
59/***************************************************************************/ 38/***************************************************************************/
60 39
40/**
41 * APIs implemented in the target tree portion:
42 * Public -
43 * pcm_init_recording
44 * pcm_close_recording
45 * pcm_rec_mux
46 * Semi-private -
47 * pcm_rec_dma_start
48 * pcm_rec_dma_stop
49 */
50
51/** These items may be implemented target specifically or need to
52 be shared semi-privately **/
53
54/* the registered callback function for when more data is available */
55pcm_more_callback_type pcm_callback_more_ready = NULL;
56/* DMA transfer in is currently active */
57bool pcm_recording = false;
58
59/* APIs implemented in the target-specific portion */
60void pcm_rec_dma_start(const void *addr, size_t size);
61void pcm_rec_dma_stop(void);
62
63/** General recording state **/
61static bool is_recording; /* We are recording */ 64static bool is_recording; /* We are recording */
62static bool is_paused; /* We have paused */ 65static bool is_paused; /* We have paused */
66static bool is_stopping; /* We are currently stopping */
63static bool is_error; /* An error has occured */ 67static bool is_error; /* An error has occured */
64 68
65static unsigned long num_rec_bytes; /* Num bytes recorded */ 69/** Stats on encoded data for current file **/
66static unsigned long num_file_bytes; /* Num bytes written to current file */ 70static size_t num_rec_bytes; /* Num bytes recorded */
67static int error_count; /* Number of DMA errors */ 71static unsigned long num_rec_samples; /* Number of PCM samples recorded */
68static unsigned long num_pcm_samples; /* Num pcm samples written to current file */
69
70static long record_start_time; /* current_tick when recording was started */
71static long pause_start_time; /* current_tick when pause was started */
72static unsigned int sample_rate; /* Sample rate at time of recording start */
73static int rec_source; /* Current recording source */
74 72
75static int wav_file; 73/** Stats on encoded data for all files from start to stop **/
76static char recording_filename[MAX_PATH]; 74static unsigned long long accum_rec_bytes; /* total size written to chunks */
75static unsigned long long accum_pcm_samples; /* total pcm count processed */
77 76
78static volatile bool init_done, close_done, record_done; 77/* Keeps data about current file and is sent as event data for codec */
79static volatile bool stop_done, pause_done, resume_done, new_file_done; 78static struct enc_file_event_data rec_fdata IDATA_ATTR =
80 79{
81static int peak_left, peak_right; 80 .chunk = NULL,
81 .new_enc_size = 0,
82 .new_num_pcm = 0,
83 .rec_file = -1,
84 .num_pcm_samples = 0
85};
82 86
83#ifdef IAUDIO_X5 87/** These apply to current settings **/
84#define SET_IIS_PLAY(x) IIS1CONFIG = (x); 88static int rec_source; /* current rec_source setting */
85#define SET_IIS_REC(x) IIS1CONFIG = (x); 89static int rec_frequency; /* current frequency setting */
86#else 90static unsigned long sample_rate; /* Sample rate in HZ */
87#define SET_IIS_PLAY(x) IIS2CONFIG = (x); 91static int num_channels; /* Current number of channels */
88#define SET_IIS_REC(x) IIS1CONFIG = (x); 92static struct encoder_config enc_config; /* Current encoder configuration */
89#endif
90 93
91/**************************************************************************** 94/****************************************************************************
92 use 2 circular buffers of same size: 95 use 2 circular buffers:
93 rec_buffer=DMA output buffer: chunks (8192 Bytes) of raw pcm audio data 96 pcm_buffer=DMA output buffer: chunks (8192 Bytes) of raw pcm audio data
94 enc_buffer=encoded audio buffer: storage for encoder output data 97 enc_buffer=encoded audio buffer: storage for encoder output data
95 98
96 Flow: 99 Flow:
97 1. when entering recording_screen DMA feeds the ringbuffer rec_buffer 100 1. when entering recording_screen DMA feeds the ringbuffer pcm_buffer
98 2. if enough pcm data are available the encoder codec does encoding of pcm 101 2. if enough pcm data are available the encoder codec does encoding of pcm
99 chunks (4-8192 Bytes) into ringbuffer enc_buffer in codec_thread 102 chunks (4-8192 Bytes) into ringbuffer enc_buffer in codec_thread
100 3. pcmrec_callback detects enc_buffer 'near full' and writes data to disk 103 3. pcmrec_callback detects enc_buffer 'near full' and writes data to disk
101 104
102 Functions calls: 105 Functions calls (basic encoder steps):
103 1.main: codec_load_encoder(); start the encoder 106 1.main: audio_load_encoder(); start the encoder
104 2.encoder: enc_get_inputs(); get encoder buffsize, mono/stereo, quality 107 2.encoder: enc_get_inputs(); get encoder recording settings
105 3.encoder: enc_set_parameters(); set the encoder parameters (max.chunksize) 108 3.encoder: enc_set_parameters(); set the encoder parameters
106 4.encoder: enc_get_wav_data(); get n bytes of unprocessed pcm data 109 4.encoder: enc_get_pcm_data(); get n bytes of unprocessed pcm data
107 5.encoder: enc_wavbuf_near_empty();if true: reduce cpu_boost 110 5.encoder: enc_pcm_buf_near_empty(); if 1: reduce cpu_boost
108 6.encoder: enc_alloc_chunk(); get a ptr to next enc chunk 111 6.encoder: enc_alloc_chunk(); get a ptr to next enc chunk
109 7.encoder: <process enc chunk> compress and store data to enc chunk 112 7.encoder: <process enc chunk> compress and store data to enc chunk
110 8.encoder: enc_free_chunk(); inform main about chunk process finished 113 8.encoder: enc_free_chunk(); inform main about chunk process finished
111 9.encoder: repeat 4. to 8. 114 9.encoder: repeat 4. to 8.
112 A.main: enc_set_header_callback(); create the current format header (file) 115 A.pcmrec: enc_events_callback(); called for certain events
113****************************************************************************/ 116****************************************************************************/
114#define NUM_CHUNKS 256 /* Power of 2 */ 117
115#define CHUNK_SIZE 8192 /* Power of 2 */ 118/** buffer parameters where incoming PCM data is placed **/
116#define MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */ 119#define PCM_NUM_CHUNKS 256 /* Power of 2 */
117#define CHUNK_MASK (NUM_CHUNKS * CHUNK_SIZE - 1) 120#define PCM_CHUNK_SIZE 8192 /* Power of 2 */
118#define WRITE_THRESHOLD (44100 * 5 / enc_samp_per_chunk) /* 5sec */ 121#define PCM_CHUNK_MASK (PCM_NUM_CHUNKS*PCM_CHUNK_SIZE - 1)
119#define GET_CHUNK(x) (long*)(&rec_buffer[x]) 122
120#define GET_ENC_CHUNK(x) (long*)(&enc_buffer[enc_chunk_size*(x)]) 123#define GET_PCM_CHUNK(offset) ((long *)(pcm_buffer + (offset)))
121 124#define GET_ENC_CHUNK(index) ENC_CHUNK_HDR(enc_buffer + enc_chunk_size*(index))
122static int audio_enc_id; /* current encoder id */ 125
123static unsigned char *rec_buffer; /* Circular recording buffer */ 126#define INC_ENC_INDEX(index) \
124static unsigned char *enc_buffer; /* Circular encoding buffer */ 127 { if (++index >= enc_num_chunks) index = 0; }
125static unsigned char *enc_head_buffer; /* encoder header buffer */ 128#define DEC_ENC_INDEX(index) \
126static int enc_head_size; /* used size in header buffer */ 129 { if (--index < 0) index = enc_num_chunks - 1; }
127static int write_pos; /* Current chunk pos for DMA writing */ 130
128static int read_pos; /* Current chunk pos for encoding */ 131static size_t rec_buffer_size; /* size of available buffer */
129static long pre_record_ticks;/* pre-record time expressed in ticks */ 132static unsigned char *pcm_buffer; /* circular recording buffer */
130static int enc_wr_index; /* Current encoding chunk write index */ 133static unsigned char *enc_buffer; /* circular encoding buffer */
131static int enc_rd_index; /* Current encoding chunk read index */ 134static volatile int dma_wr_pos; /* current DMA write pos */
132static int enc_chunk_size; /* maximum encoder chunk size */ 135static int pcm_rd_pos; /* current PCM read pos */
136static volatile bool dma_lock; /* lock DMA write position */
137static unsigned long pre_record_ticks;/* pre-record time in ticks */
138static int enc_wr_index; /* encoder chunk write index */
139static int enc_rd_index; /* encoder chunk read index */
133static int enc_num_chunks; /* number of chunks in ringbuffer */ 140static int enc_num_chunks; /* number of chunks in ringbuffer */
134static int enc_buffer_size; /* encode buffer size */ 141static size_t enc_chunk_size; /* maximum encoder chunk size */
135static int enc_channels; /* 1=mono 2=stereo */ 142static size_t enc_data_size; /* maximum data size for encoder */
136static int enc_quality; /* mp3: 64,96,128,160,192,320 kBit */ 143static unsigned long enc_sample_rate; /* sample rate used by encoder */
137static int enc_samp_per_chunk;/* pcm samples per encoder chunk */
138static bool wav_queue_empty; /* all wav chunks processed? */ 144static bool wav_queue_empty; /* all wav chunks processed? */
139static unsigned long avrg_bit_rate; /* average bit rates from chunks */
140static unsigned long curr_bit_rate; /* cumulated bit rates from chunks */
141static unsigned long curr_chunk_cnt; /* number of processed chunks */
142 145
143void (*enc_set_header_callback)(void *head_buffer, int head_size, 146/** file flushing **/
144 int num_pcm_samples, bool is_file_header); 147static int write_threshold; /* max chunk limit for data flush */
148static int panic_threshold; /* boost thread prio when here */
149static int spinup_time = -1;/* last ata_spinup_time */
150
151/** encoder events **/
152static void (*enc_events_callback)(enum enc_events event, void *data);
153
154/** Path queue for files to write **/
155#define FNQ_MIN_NUM_PATHS 16 /* minimum number of paths to hold */
156static unsigned char *fn_queue; /* pointer to first filename */
157static ssize_t fnq_size; /* capacity of queue in bytes */
158static int fnq_rd_pos; /* current read position */
159static int fnq_wr_pos; /* current write position */
145 160
146/***************************************************************************/ 161/***************************************************************************/
147 162
148static struct event_queue pcmrec_queue; 163static struct event_queue pcmrec_queue;
149static long pcmrec_stack[2*DEFAULT_STACK_SIZE/sizeof(long)]; 164static long pcmrec_stack[3*DEFAULT_STACK_SIZE/sizeof(long)];
150static const char pcmrec_thread_name[] = "pcmrec"; 165static const char pcmrec_thread_name[] = "pcmrec";
151 166
152static void pcmrec_thread(void); 167static void pcmrec_thread(void);
153static void pcmrec_dma_start(void);
154static void pcmrec_dma_stop(void);
155static void close_wave(void);
156 168
157/* Event IDs */ 169/* Event values which are also single-bit flags */
158#define PCMREC_INIT 1 /* Enable recording */ 170#define PCMREC_INIT 0x00000001 /* enable recording */
159#define PCMREC_CLOSE 2 171#define PCMREC_CLOSE 0x00000002
160 172
161#define PCMREC_START 3 /* Start a new recording */ 173#define PCMREC_START 0x00000004 /* start recording (when stopped) */
162#define PCMREC_STOP 4 /* Stop the current recording */ 174#define PCMREC_STOP 0x00000008 /* stop the current recording */
163#define PCMREC_PAUSE 10 175#define PCMREC_PAUSE 0x00000010 /* pause the current recording */
164#define PCMREC_RESUME 11 176#define PCMREC_RESUME 0x00000020 /* resume the current recording */
165#define PCMREC_NEW_FILE 12 177#define PCMREC_NEW_FILE 0x00000040 /* start new file (when recording) */
166#define PCMREC_SET_GAIN 13 178#define PCMREC_SET_GAIN 0x00000080
179#define PCMREC_FLUSH_NUM 0x00000100 /* flush a number of files out */
180#define PCMREC_FINISH_STOP 0x00000200 /* finish the stopping recording */
167 181
168/*******************************************************************/ 182/* mask for signaling events */
169/* Functions that are not executing in the pcmrec_thread first */ 183static volatile long pcm_thread_event_mask;
170/*******************************************************************/
171 184
172/* Creates pcmrec_thread */ 185static void pcm_thread_sync_post(long event, void *data)
173void pcm_rec_init(void)
174{ 186{
175 queue_init(&pcmrec_queue, true); 187 pcm_thread_event_mask &= ~event;
176 create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), 188 queue_post(&pcmrec_queue, event, data);
177 pcmrec_thread_name IF_PRIO(, PRIORITY_RECORDING)); 189 while(!(event & pcm_thread_event_mask))
178} 190 yield();
191} /* pcm_thread_sync_post */
179 192
193static inline void pcm_thread_signal_event(long event)
194{
195 pcm_thread_event_mask |= event;
196} /* pcm_thread_signal_event */
180 197
181int audio_get_encoder_id(void) 198static inline void pcm_thread_unsignal_event(long event)
182{ 199{
183 return audio_enc_id; 200 pcm_thread_event_mask &= ~event;
184} 201} /* pcm_thread_unsignal_event */
185 202
186/* Initializes recording: 203static inline bool pcm_thread_event_state(long signaled, long unsignaled)
187 * - Set up the UDA1380/TLV320 for recording 204{
188 * - Prepare for DMA transfers 205 return ((signaled | unsignaled) & pcm_thread_event_mask) == signaled;
189 */ 206} /* pcm_thread_event_state */
190 207
191void audio_init_recording(unsigned int buffer_offset) 208static void pcm_thread_wait_for_stop(void)
192{ 209{
193 (void)buffer_offset; 210 if (is_stopping)
211 {
212 logf("waiting for stop to finish");
213 while (is_stopping)
214 yield();
215 }
216} /* pcm_thread_wait_for_stop */
194 217
195 init_done = false; 218/*******************************************************************/
196 queue_post(&pcmrec_queue, PCMREC_INIT, 0); 219/* Functions that are not executing in the pcmrec_thread first */
220/*******************************************************************/
197 221
198 while(!init_done) 222/* Callback for when more data is ready */
199 sleep_thread(1); 223static void pcm_rec_have_more(unsigned char **data, size_t *size)
200}
201
202void audio_close_recording(void)
203{ 224{
204 close_done = false; 225 if (*size != 0)
205 queue_post(&pcmrec_queue, PCMREC_CLOSE, 0); 226 {
227 /* some error condition */
228 if (*size == DMA_REC_ERROR_DMA)
229 {
230 /* Flush recorded data to disk and stop recording */
231 queue_post(&pcmrec_queue, PCMREC_STOP, NULL);
232 return;
233 }
234 /* else try again next transmission */
235 }
236 else if (!dma_lock)
237 {
238 /* advance write position */
239 dma_wr_pos = (dma_wr_pos + PCM_CHUNK_SIZE) & PCM_CHUNK_MASK;
240 }
206 241
207 while(!close_done) 242 *data = (unsigned char *)GET_PCM_CHUNK(dma_wr_pos);
208 sleep_thread(1); 243 *size = PCM_CHUNK_SIZE;
244} /* pcm_rec_have_more */
209 245
210 audio_remove_encoder(); 246/** pcm_rec_* group **/
211} 247void pcm_rec_error_clear(void)
248{
249 is_error = false;
250} /* pcm_rec_error_clear */
212 251
213unsigned long pcm_rec_status(void) 252unsigned long pcm_rec_status(void)
214{ 253{
@@ -216,165 +255,223 @@ unsigned long pcm_rec_status(void)
216 255
217 if (is_recording) 256 if (is_recording)
218 ret |= AUDIO_STATUS_RECORD; 257 ret |= AUDIO_STATUS_RECORD;
258
219 if (is_paused) 259 if (is_paused)
220 ret |= AUDIO_STATUS_PAUSE; 260 ret |= AUDIO_STATUS_PAUSE;
261
221 if (is_error) 262 if (is_error)
222 ret |= AUDIO_STATUS_ERROR; 263 ret |= AUDIO_STATUS_ERROR;
223 if (!is_recording && pre_record_ticks && init_done && !close_done) 264
265 if (!is_recording && pre_record_ticks &&
266 pcm_thread_event_state(PCMREC_INIT, PCMREC_CLOSE))
224 ret |= AUDIO_STATUS_PRERECORD; 267 ret |= AUDIO_STATUS_PRERECORD;
225 268
226 return ret; 269 return ret;
227} 270} /* pcm_rec_status */
228 271
229int pcm_rec_current_bitrate(void) 272int pcm_rec_current_bitrate(void)
230{ 273{
231 return avrg_bit_rate; 274 if (accum_pcm_samples == 0)
232} 275 return 0;
233 276
234unsigned long audio_recorded_time(void) 277 return (int)(8*accum_rec_bytes*enc_sample_rate / (1000*accum_pcm_samples));
278} /* pcm_rec_current_bitrate */
279
280int pcm_rec_encoder_afmt(void)
235{ 281{
236 if (is_recording) 282 return enc_config.afmt;
283} /* pcm_rec_encoder_afmt */
284
285int pcm_rec_rec_format(void)
237 { 286 {
238 if (is_paused) 287 return afmt_rec_format[enc_config.afmt];
239 return pause_start_time - record_start_time; 288} /* pcm_rec_rec_format */
240 else
241 return current_tick - record_start_time;
242 }
243 289
244 return 0; 290unsigned long pcm_rec_sample_rate(void)
245} 291{
292 /* Which is better ?? */
293#if 0
294 return enc_sample_rate;
295#endif
296 return sample_rate;
297} /* audio_get_sample_rate */
246 298
247unsigned long audio_num_recorded_bytes(void) 299/**
300 * Creates pcmrec_thread
301 */
302void pcm_rec_init(void)
248{ 303{
249 if (is_recording) 304 queue_init(&pcmrec_queue, true);
250 return num_rec_bytes; 305 create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack),
306 pcmrec_thread_name, PRIORITY_RECORDING);
307} /* pcm_rec_init */
251 308
309/** audio_* group **/
310
311void audio_init_recording(unsigned int buffer_offset)
312{
313 (void)buffer_offset;
314 pcm_thread_wait_for_stop();
315 pcm_thread_sync_post(PCMREC_INIT, NULL);
316} /* audio_init_recording */
317
318void audio_close_recording(void)
319{
320 pcm_thread_wait_for_stop();
321 pcm_thread_sync_post(PCMREC_CLOSE, NULL);
322 /* reset pcm to defaults (playback only) */
323 pcm_set_frequency(-1);
324 pcm_set_monitor(-1);
325 pcm_set_rec_source(-1);
326#ifdef HAVE_TLV320
327 /* tlv320 screeches if left at 88.2 with no inputs */
328 pcm_apply_settings(true);
329#endif
330 audio_remove_encoder();
331} /* audio_close_recording */
332
333unsigned long audio_recorded_time(void)
334{
335 if (!is_recording || enc_sample_rate == 0)
252 return 0; 336 return 0;
253}
254 337
255#ifdef HAVE_SPDIF_IN 338 /* return actual recorded time a la encoded data even if encoder rate
256/* Only the last six of these are standard rates, but all sample rates are 339 doesn't match the pcm rate */
257 * possible, so we support some other common ones as well. 340 return (long)(HZ*(unsigned long long)num_rec_samples / enc_sample_rate);
258 */ 341} /* audio_recorded_time */
259static unsigned long spdif_sample_rates[] = {
260 8000, 11025, 12000, 16000, 22050, 24000,
261 32000, 44100, 48000, 64000, 88200, 96000
262};
263 342
264/* Return SPDIF sample rate. Since we base our reading on the actual SPDIF 343unsigned long audio_num_recorded_bytes(void)
265 * sample rate (which might be a bit inaccurate), we round off to the closest
266 * sample rate that is supported by SPDIF.
267 */
268unsigned long audio_get_spdif_sample_rate(void)
269{ 344{
270 int i = 0; 345 if (!is_recording)
271 unsigned long measured_rate; 346 return 0;
272 const int upper_bound = sizeof(spdif_sample_rates)/sizeof(long) - 1; 347
348 return num_rec_bytes;
349} /* audio_num_recorded_bytes */
273 350
351#ifdef HAVE_SPDIF_IN
352/* Return current SPDIF sample rate */
353static unsigned long measure_spdif_sample_rate(void)
354{
274 /* The following formula is specified in MCF5249 user's manual section 355 /* The following formula is specified in MCF5249 user's manual section
275 * 17.6.1. The 3*(1 << 13) part will need changing if the setup of the 356 * 17.6.1. The 128 divide is because of the fact that the SPDIF clock is
276 * PHASECONFIG register is ever changed. The 128 divide is because of the 357 * the sample rate times 128. Keep "3*(1 << 13)" part in sync with
277 * fact that the SPDIF clock is the sample rate times 128. 358 * PHASECONFIG setup in pcm_init_recording in pcm-coldfire.c.
278 */ 359 */
279 measured_rate = (unsigned long)((unsigned long long)FREQMEAS*CPU_FREQ/ 360 return (unsigned long)((unsigned long long)FREQMEAS*CPU_FREQ /
280 ((1 << 15)*3*(1 << 13))/128); 361 ((1 << 15)*3*(1 << 13))/128);
281 /* Find which SPDIF sample rate we're closest to. */ 362} /* measure_spdif_sample_rate */
282 while (spdif_sample_rates[i] < measured_rate && i < upper_bound) ++i;
283 if (i > 0 && i < upper_bound)
284 {
285 long diff1 = measured_rate - spdif_sample_rates[i - 1];
286 long diff2 = spdif_sample_rates[i] - measured_rate;
287 363
288 if (diff2 > diff1) --i; 364/**
289 } 365 * Return SPDIF sample rate index in audio_master_sampr_list. Since we base
290 return i; 366 * our reading on the actual SPDIF sample rate (which might be a bit
291} 367 * inaccurate), we round off to the closest sample rate that is supported by
292#endif 368 * SPDIF.
369 */
370int audio_get_spdif_sample_rate(void)
371{
372 unsigned long measured_rate = measure_spdif_sample_rate();
373 /* Find which SPDIF sample rate we're closest to. */
374 return round_value_to_list32(measured_rate, audio_master_sampr_list,
375 SAMPR_NUM_FREQ, false);
376} /* audio_get_spdif_sample_rate */
293 377
294#if 0
295/* not needed atm */
296#ifdef HAVE_SPDIF_POWER 378#ifdef HAVE_SPDIF_POWER
297static bool spdif_power_setting; 379static bool spdif_power_setting;
298 380
299void audio_set_spdif_power_setting(bool on) 381void audio_set_spdif_power_setting(bool on)
300{ 382{
301 spdif_power_setting = on; 383 spdif_power_setting = on;
302} 384} /* audio_set_spdif_power_setting */
385
386bool audio_get_spdif_power_setting(void)
387{
388 return spdif_power_setting;
389} /* audio_get_spdif_power_setting */
303#endif 390#endif
391
392void audio_spdif_set_monitor(int monitor_spdif)
393{
394 EBU1CONFIG = 0x800; /* Reset before reprogram */
395
396 if (monitor_spdif > 0)
397 {
398#ifdef HAVE_SPDIF_POWER
399 EBU1CONFIG = spdif_power_setting ? (1 << 2) : 0;
400 /* Input source is EBUin1, Feed-through monitoring if desired */
401#else
402 EBU1CONFIG = (1 << 2);
403 /* Input source is EBUin1, Feed-through monitoring */
304#endif 404#endif
405 }
406 else if (monitor_spdif == 0)
407 {
408 /* SCLK2, TXSRC = IIS1recv, validity, normal operation */
409 EBU1CONFIG = (7 << 12) | (4 << 8) | (1 << 5) | (5 << 2);
410 }
411} /* audio_spdif_set_monitor */
412
413#endif /* HAVE_SPDIF_IN */
305 414
306/** 415/**
307 * Sets recording parameters 416 * Sets recording parameters
308 *
309 * This functions starts feeding the CPU with audio data over the I2S bus
310 */ 417 */
311void audio_set_recording_options(int frequency, int quality, 418void audio_set_recording_options(struct audio_recording_options *options)
312 int source, int channel_mode,
313 bool editable, int prerecord_time)
314{ 419{
315 /* TODO: */ 420 pcm_thread_wait_for_stop();
316 (void)editable;
317 421
318 /* NOTE: Coldfire UDA based recording does not yet support anything other 422 /* stop DMA transfer */
319 * than 44.1kHz sampling rate, so we limit it to that case here now. SPDIF 423 dma_lock = true;
320 * based recording will overwrite this value with the proper sample rate in 424 pcm_stop_recording();
321 * audio_record(), and will not be affected by this.
322 */
323 frequency = 44100;
324 enc_quality = quality;
325 rec_source = source;
326 enc_channels = channel_mode == CHN_MODE_MONO ? 1 : 2;
327 pre_record_ticks = prerecord_time * HZ;
328 425
329 switch (source) 426 rec_frequency = options->rec_frequency;
330 { 427 rec_source = options->rec_source;
331 case AUDIO_SRC_MIC: 428 num_channels = options->rec_channels == 1 ? 1 : 2;
332 case AUDIO_SRC_LINEIN: 429 pre_record_ticks = options->rec_prerecord_time * HZ;
333#ifdef HAVE_FMRADIO_IN 430 enc_config = options->enc_config;
334 case AUDIO_SRC_FMRADIO: 431 enc_config.afmt = rec_format_afmt[enc_config.rec_format];
335#endif
336 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */
337 DATAINCONTROL = 0xc020;
338 break;
339 432
340#ifdef HAVE_SPDIF_IN 433#ifdef HAVE_SPDIF_IN
341 case AUDIO_SRC_SPDIF: 434 if (rec_source == AUDIO_SRC_SPDIF)
342 /* Int. when 6 samples in FIFO. PDIR2 source = ebu1RcvData */ 435 {
343 DATAINCONTROL = 0xc038; 436 /* must measure SPDIF sample rate before configuring codecs */
344 break; 437 unsigned long sr = measure_spdif_sample_rate();
345#endif /* HAVE_SPDIF_IN */ 438 /* round to master list for SPDIF rate */
439 int index = round_value_to_list32(sr, audio_master_sampr_list,
440 SAMPR_NUM_FREQ, false);
441 sample_rate = audio_master_sampr_list[index];
442 /* round to HW playback rates for monitoring */
443 index = round_value_to_list32(sr, hw_freq_sampr,
444 HW_NUM_FREQ, false);
445 pcm_set_frequency(hw_freq_sampr[index]);
446 /* encoders with a limited number of rates do their own rounding */
447 }
448 else
449#endif
450 {
451 /* set sample rate from frequency selection */
452 sample_rate = rec_freq_sampr[rec_frequency];
453 pcm_set_frequency(sample_rate);
346 } 454 }
347 455
348 sample_rate = frequency; 456 pcm_set_monitor(rec_source);
349 457 pcm_set_rec_source(rec_source);
350 /* Monitoring: route the signals through the coldfire audio interface. */
351 458
352 SET_IIS_PLAY(0x800); /* Reset before reprogram */ 459 /* apply pcm settings to hardware */
460 pcm_apply_settings(true);
353 461
354#ifdef HAVE_SPDIF_IN 462 if (audio_load_encoder(enc_config.afmt))
355 if (source == AUDIO_SRC_SPDIF)
356 { 463 {
357 /* SCLK2 = Audioclk/4 (can't use EBUin clock), TXSRC = EBU1rcv, 64 bclk/wclk */ 464 /* start DMA transfer */
358 IIS2CONFIG = (6 << 12) | (7 << 8) | (4 << 2); 465 pcm_record_data(pcm_rec_have_more, NULL, 0);
359 /* S/PDIF feed-through already configured */ 466 /* do unlock after starting to prevent preincrement of dma_wr_pos */
467 dma_lock = pre_record_ticks == 0;
360 } 468 }
361 else 469 else
362 { 470 {
363 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */ 471 logf("set rec opt: enc load failed");
364 IIS2CONFIG = (8 << 12) | (4 << 8) | (4 << 2); 472 is_error = true;
365
366 EBU1CONFIG = 0x800; /* Reset before reprogram */
367 /* SCLK2, TXSRC = IIS1recv, validity, normal operation */
368 EBU1CONFIG = (7 << 12) | (4 << 8) | (1 << 5) | (5 << 2);
369 }
370#else
371 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */
372 SET_IIS_PLAY( (8 << 12) | (4 << 8) | (4 << 2) );
373#endif
374
375 audio_load_encoder(rec_quality_info_afmt[quality]);
376} 473}
377 474} /* audio_set_recording_options */
378 475
379/** 476/**
380 * Note that microphone is mono, only left value is used 477 * Note that microphone is mono, only left value is used
@@ -391,8 +488,7 @@ void audio_set_recording_gain(int left, int right, int type)
391#elif defined (HAVE_TLV320) 488#elif defined (HAVE_TLV320)
392 tlv320_set_recvol(left, right, type); 489 tlv320_set_recvol(left, right, type);
393#endif 490#endif
394} 491} /* audio_set_recording_gain */
395
396 492
397/** 493/**
398 * Start recording 494 * Start recording
@@ -401,585 +497,882 @@ void audio_set_recording_gain(int left, int right, int type)
401 */ 497 */
402void audio_record(const char *filename) 498void audio_record(const char *filename)
403{ 499{
500 logf("audio_record: %s", filename);
501
502 pcm_thread_wait_for_stop();
503 pcm_thread_sync_post(PCMREC_START, (void *)filename);
504
505 logf("audio_record_done");
506} /* audio_record */
507
508void audio_new_file(const char *filename)
509{
510 logf("audio_new_file: %s", filename);
511
512 pcm_thread_wait_for_stop();
513 pcm_thread_sync_post(PCMREC_NEW_FILE, (void *)filename);
514
515 logf("audio_new_file done");
516} /* audio_new_file */
517
518void audio_stop_recording(void)
519{
520 logf("audio_stop_recording");
521
522 pcm_thread_wait_for_stop();
523
404 if (is_recording) 524 if (is_recording)
405 { 525 dma_lock = true; /* fix DMA write ptr at current position */
406 logf("record while recording"); 526
407 return; 527 pcm_thread_sync_post(PCMREC_STOP, NULL);
408 } 528
529 logf("audio_stop_recording done");
530} /* audio_stop_recording */
531
532void audio_pause_recording(void)
533{
534 logf("audio_pause_recording");
409 535
410 strncpy(recording_filename, filename, MAX_PATH - 1); 536 pcm_thread_wait_for_stop();
411 recording_filename[MAX_PATH - 1] = 0;
412 537
413#ifdef HAVE_SPDIF_IN 538 if (is_recording)
414 if (rec_source == AUDIO_SRC_SPDIF) 539 dma_lock = true; /* fix DMA write ptr at current position */
415 sample_rate = audio_get_spdif_sample_rate();
416#endif
417 540
418 record_done = false; 541 pcm_thread_sync_post(PCMREC_PAUSE, NULL);
419 queue_post(&pcmrec_queue, PCMREC_START, 0); 542 logf("audio_pause_recording done");
543} /* audio_pause_recording */
420 544
421 while(!record_done) 545void audio_resume_recording(void)
422 sleep_thread(1); 546{
423} 547 logf("audio_resume_recording");
424 548
549 pcm_thread_wait_for_stop();
550 pcm_thread_sync_post(PCMREC_RESUME, NULL);
425 551
426void audio_new_file(const char *filename) 552 logf("audio_resume_recording done");
553} /* audio_resume_recording */
554
555/***************************************************************************/
556/* */
557/* Functions that execute in the context of pcmrec_thread */
558/* */
559/***************************************************************************/
560
561/** Filename Queue **/
562
563/* returns true if the queue is empty */
564static inline bool pcmrec_fnq_is_empty(void)
427{ 565{
428 logf("pcm_new_file"); 566 return fnq_rd_pos == fnq_wr_pos;
567} /* pcmrec_fnq_is_empty */
568
569/* empties the filename queue */
570static inline void pcmrec_fnq_set_empty(void)
571{
572 fnq_rd_pos = fnq_wr_pos;
573} /* pcmrec_fnq_set_empty */
429 574
430 new_file_done = false; 575/* returns true if the queue is full */
576static bool pcmrec_fnq_is_full(void)
577{
578 ssize_t size = fnq_wr_pos - fnq_rd_pos;
579 if (size < 0)
580 size += fnq_size;
431 581
432 strncpy(recording_filename, filename, MAX_PATH - 1); 582 return size >= fnq_size - MAX_PATH;
433 recording_filename[MAX_PATH - 1] = 0; 583} /* pcmrec_fnq_is_full */
434 584
435 queue_post(&pcmrec_queue, PCMREC_NEW_FILE, 0); 585/* queue another filename - will overwrite oldest one if full */
586static bool pcmrec_fnq_add_filename(const char *filename)
587{
588 strncpy(fn_queue + fnq_wr_pos, filename, MAX_PATH);
436 589
437 while(!new_file_done) 590 if ((fnq_wr_pos += MAX_PATH) >= fnq_size)
438 sleep_thread(1); 591 fnq_wr_pos = 0;
439 592
440 logf("pcm_new_file done"); 593 if (fnq_rd_pos != fnq_wr_pos)
441} 594 return true;
442 595
443/** 596 /* queue full */
444 * 597 if ((fnq_rd_pos += MAX_PATH) >= fnq_size)
445 */ 598 fnq_rd_pos = 0;
446void audio_stop_recording(void) 599
600 return true;
601} /* pcmrec_fnq_add_filename */
602
603/* replace the last filename added */
604static bool pcmrec_fnq_replace_tail(const char *filename)
447{ 605{
448 if (!is_recording) 606 int pos;
449 return; 607
608 if (pcmrec_fnq_is_empty())
609 return false;
610
611 pos = fnq_wr_pos - MAX_PATH;
612 if (pos < 0)
613 pos = fnq_size - MAX_PATH;
614
615 strncpy(fn_queue + pos, filename, MAX_PATH);
616
617 return true;
618} /* pcmrec_fnq_replace_tail */
450 619
451 logf("pcm_stop"); 620/* pulls the next filename from the queue */
621static bool pcmrec_fnq_get_filename(char *filename)
622{
623 if (pcmrec_fnq_is_empty())
624 return false;
625
626 if (filename)
627 strncpy(filename, fn_queue + fnq_rd_pos, MAX_PATH);
452 628
453 is_paused = true; /* fix pcm write ptr at current position */ 629 if ((fnq_rd_pos += MAX_PATH) >= fnq_size)
454 stop_done = false; 630 fnq_rd_pos = 0;
455 queue_post(&pcmrec_queue, PCMREC_STOP, 0);
456 631
457 while(!stop_done) 632 return true;
458 sleep_thread(1); 633} /* pcmrec_fnq_get_filename */
459 634
460 logf("pcm_stop done"); 635/* close the file number pointed to by fd_p */
461} 636static void pcmrec_close_file(int *fd_p)
637{
638 if (*fd_p < 0)
639 return; /* preserve error */
462 640
463void audio_pause_recording(void) 641 close(*fd_p);
642 *fd_p = -1;
643} /* pcmrec_close_file */
644
645/** Data Flushing **/
646
647/**
648 * called after callback to update sizes if codec changed the amount of data
649 * a chunk represents
650 */
651static inline void pcmrec_update_sizes_inl(size_t prev_enc_size,
652 unsigned long prev_num_pcm)
464{ 653{
465 if (!is_recording) 654 if (rec_fdata.new_enc_size != prev_enc_size)
466 { 655 {
467 logf("pause when not recording"); 656 ssize_t size_diff = rec_fdata.new_enc_size - prev_enc_size;
468 return; 657 num_rec_bytes += size_diff;
658 accum_rec_bytes += size_diff;
469 } 659 }
470 if (is_paused) 660
661 if (rec_fdata.new_num_pcm != prev_num_pcm)
471 { 662 {
472 logf("pause when paused"); 663 unsigned long pcm_diff = rec_fdata.new_num_pcm - prev_num_pcm;
473 return; 664 num_rec_samples += pcm_diff;
665 accum_pcm_samples += pcm_diff;
474 } 666 }
475 667} /* pcmrec_update_sizes_inl */
476 pause_done = false;
477 queue_post(&pcmrec_queue, PCMREC_PAUSE, 0);
478 668
479 while(!pause_done) 669/* don't need to inline every instance */
480 sleep_thread(1); 670static void pcmrec_update_sizes(size_t prev_enc_size,
481} 671 unsigned long prev_num_pcm)
672{
673 pcmrec_update_sizes_inl(prev_enc_size, prev_num_pcm);
674} /* pcmrec_update_sizes */
482 675
483void audio_resume_recording(void) 676static void pcmrec_start_file(void)
484{ 677{
485 if (!is_paused) 678 size_t enc_size = rec_fdata.new_enc_size;
679 unsigned long num_pcm = rec_fdata.new_num_pcm;
680 int curr_rec_file = rec_fdata.rec_file;
681 char filename[MAX_PATH];
682
683 /* must always pull the filename that matches with this queue */
684 if (!pcmrec_fnq_get_filename(filename))
486 { 685 {
487 logf("resume when not paused"); 686 logf("start file: fnq empty");
488 return; 687 *filename = '\0';
688 is_error = true;
689 }
690 else if (is_error)
691 {
692 logf("start file: is_error already");
693 }
694 else if (curr_rec_file >= 0)
695 {
696 /* Any previous file should have been closed */
697 logf("start file: file already open");
698 is_error = true;
489 } 699 }
490 700
491 resume_done = false; 701 if (is_error)
492 queue_post(&pcmrec_queue, PCMREC_RESUME, 0); 702 rec_fdata.chunk->flags |= CHUNKF_ERROR;
493 703
494 while(!resume_done) 704 /* encoder can set error flag here and should increase
495 sleep_thread(1); 705 enc_new_size and pcm_new_size to reflect additional
496} 706 data written if any */
707 rec_fdata.filename = filename;
708 enc_events_callback(ENC_START_FILE, &rec_fdata);
709
710 if (!is_error && (rec_fdata.chunk->flags & CHUNKF_ERROR))
711 {
712 logf("start file: enc error");
713 is_error = true;
714 }
497 715
498/* return peaks as int, so convert from short first 716 if (is_error)
499 note that peak values are always positive */ 717 {
500void pcm_rec_get_peaks(int *left, int *right) 718 pcmrec_close_file(&curr_rec_file);
719 /* Write no more to this file */
720 rec_fdata.chunk->flags |= CHUNKF_END_FILE;
721 }
722 else
723 {
724 pcmrec_update_sizes(enc_size, num_pcm);
725 }
726
727 rec_fdata.chunk->flags &= ~CHUNKF_START_FILE;
728} /* pcmrec_start_file */
729
730static inline void pcmrec_write_chunk(void)
501{ 731{
502 if (left) 732 size_t enc_size = rec_fdata.new_enc_size;
503 *left = peak_left; 733 unsigned long num_pcm = rec_fdata.new_num_pcm;
504 if (right)
505 *right = peak_right;
506 peak_left = 0;
507 peak_right = 0;
508}
509 734
510/***************************************************************************/ 735 if (is_error)
511/* Functions that executes in the context of pcmrec_thread */ 736 rec_fdata.chunk->flags |= CHUNKF_ERROR;
512/***************************************************************************/ 737
738 enc_events_callback(ENC_WRITE_CHUNK, &rec_fdata);
739
740 if ((long)rec_fdata.chunk->flags >= 0)
741 {
742 pcmrec_update_sizes_inl(enc_size, num_pcm);
743 }
744 else if (!is_error)
745 {
746 logf("wr chk enc error %d %d",
747 rec_fdata.chunk->enc_size, rec_fdata.chunk->num_pcm);
748 is_error = true;
749 }
750} /* pcmrec_write_chunk */
751
752static void pcmrec_end_file(void)
753{
754 /* all data in output buffer for current file will have been
755 written and encoder can now do any nescessary steps to
756 finalize the written file */
757 size_t enc_size = rec_fdata.new_enc_size;
758 unsigned long num_pcm = rec_fdata.new_num_pcm;
759
760 enc_events_callback(ENC_END_FILE, &rec_fdata);
761
762 if (!is_error)
763 {
764 if (rec_fdata.chunk->flags & CHUNKF_ERROR)
765 {
766 logf("end file: enc error");
767 is_error = true;
768 }
769 else
770 {
771 pcmrec_update_sizes(enc_size, num_pcm);
772 }
773 }
774
775 /* Force file close if error */
776 if (is_error)
777 pcmrec_close_file(&rec_fdata.rec_file);
778
779 rec_fdata.chunk->flags &= ~CHUNKF_END_FILE;
780} /* pcmrec_end_file */
513 781
514/** 782/**
515 * Process the chunks 783 * Process the chunks
516 * 784 *
517 * This function is called when queue_get_w_tmo times out. 785 * This function is called when queue_get_w_tmo times out.
518 * 786 *
519 * Other functions can also call this function with flush = true when 787 * Set flush_num to the number of files to flush to disk.
520 * they want to save everything in the buffers to disk. 788 * flush_num = -1 to flush all available chunks to disk.
789 * flush_num = 0 normal write thresholding
790 * flush_num = 1 or greater - all available chunks of current file plus
791 * flush_num file starts if first chunk has been processed.
521 * 792 *
522 */ 793 */
523static void pcmrec_callback(bool flush) 794static void pcmrec_flush(unsigned flush_num)
524{ 795{
525 int i, num_ready, size_yield; 796 static unsigned long last_flush_tick = 0;
526 long *enc_chunk, chunk_size; 797 unsigned long start_tick;
527 798 int num_ready, num;
528 if (!is_recording && !flush) 799 int prio;
529 return; 800 int i;
530 801
531 num_ready = enc_wr_index - enc_rd_index; 802 num_ready = enc_wr_index - enc_rd_index;
532 if (num_ready < 0) 803 if (num_ready < 0)
533 num_ready += enc_num_chunks; 804 num_ready += enc_num_chunks;
534 805
535 /* calculate an estimate of recorded bytes */ 806 num = num_ready;
536 num_rec_bytes = num_file_bytes + num_ready * /* enc_chunk_size */
537 ((avrg_bit_rate * 1000 / 8 * enc_samp_per_chunk + 22050) / 44100);
538 807
539 /* near full state reached: less than 5sec remaining space */ 808 if (flush_num == 0)
540 if (enc_num_chunks - num_ready < WRITE_THRESHOLD || flush)
541 { 809 {
542 logf("writing: %d (%d)", num_ready, flush); 810 if (!is_recording)
543 811 return;
544 cpu_boost_id(true, CPUBOOSTID_PCMRECORD);
545 812
546 size_yield = 0; 813 if (ata_spinup_time != spinup_time)
547 for (i=0; i<num_ready; i++)
548 { 814 {
549 enc_chunk = GET_ENC_CHUNK(enc_rd_index); 815 /* spinup time has changed, calculate new write threshold */
550 chunk_size = *enc_chunk++; 816 logf("new t spinup : %d", ata_spinup_time);
551 817 unsigned long st = spinup_time = ata_spinup_time;
552 /* safety net: if size entry got corrupted => limit */ 818
553 if (chunk_size > (long)(enc_chunk_size - sizeof(long))) 819 /* write at 5s + st remaining in enc_buffer */
554 chunk_size = enc_chunk_size - sizeof(long); 820 if (st < 2*HZ)
821 st = 2*HZ; /* my drive is usually < 250 ticks :) */
822 else if (st > 10*HZ)
823 st = 10*HZ;
824
825 write_threshold = enc_num_chunks -
826 (int)(((5ull*HZ + st)*4ull*sample_rate + (enc_chunk_size-1)) /
827 (enc_chunk_size*HZ));
828
829 if (write_threshold < 0)
830 write_threshold = 0;
831 else if (write_threshold > panic_threshold)
832 write_threshold = panic_threshold;
833
834 logf("new wr thresh: %d", write_threshold);
835 }
555 836
556 if (enc_set_header_callback != NULL) 837 if (num_ready < write_threshold)
557 enc_set_header_callback(enc_chunk, enc_chunk_size, 838 return;
558 num_pcm_samples, false);
559 839
560 if (write(wav_file, enc_chunk, chunk_size) != chunk_size) 840 /* if we're getting called too much and this isn't forced,
561 { 841 boost stat */
562 close_wave(); 842 if (current_tick - last_flush_tick < HZ/2)
563 logf("pcmrec: write err"); 843 num = panic_threshold;
564 is_error = true; 844 }
565 break;
566 }
567 845
568 num_file_bytes += chunk_size; 846 start_tick = current_tick;
569 num_pcm_samples += enc_samp_per_chunk; 847 prio = -1;
570 size_yield += chunk_size;
571 848
572 if (size_yield >= 32768) 849 logf("writing: %d (%d)", num_ready, flush_num);
573 { /* yield when 32kB written */ 850
574 size_yield = 0; 851 cpu_boost_id(true, CPUBOOSTID_PCMRECORD);
575 yield();
576 }
577 852
578 enc_rd_index = (enc_rd_index + 1) % enc_num_chunks; 853 for (i=0; i<num_ready; i++)
854 {
855 if (prio == -1 && (num >= panic_threshold ||
856 current_tick - start_tick > 10*HZ))
857 {
858 /* losing ground - boost priority until finished */
859 logf("pcmrec: boost priority");
860 prio = thread_set_priority(NULL, thread_get_priority(NULL)-1);
579 } 861 }
580 862
581 /* sync file */ 863 rec_fdata.chunk = GET_ENC_CHUNK(enc_rd_index);
582 fsync(wav_file); 864 rec_fdata.new_enc_size = rec_fdata.chunk->enc_size;
865 rec_fdata.new_num_pcm = rec_fdata.chunk->num_pcm;
583 866
584 cpu_boost_id(false, CPUBOOSTID_PCMRECORD); 867 if (rec_fdata.chunk->flags & CHUNKF_START_FILE)
868 {
869 pcmrec_start_file();
870 if (--flush_num == 0)
871 i = num_ready; /* stop on next loop - must write this
872 chunk if it has data */
873 }
585 874
586 logf("done"); 875 pcmrec_write_chunk();
587 }
588}
589 876
590/* Abort dma transfer */ 877 if (rec_fdata.chunk->flags & CHUNKF_END_FILE)
591static void pcmrec_dma_stop(void) 878 pcmrec_end_file();
592{
593 DCR1 = 0;
594 879
595 error_count++; 880 INC_ENC_INDEX(enc_rd_index);
596 881
597 DSR1 = 1; /* Clear interrupt */ 882 if (is_error)
598 IPR |= (1<<15); /* Clear pending interrupt request */ 883 break;
599 884
600 logf("dma1 stopped"); 885 if (prio == -1)
601} 886 {
887 num = enc_wr_index - enc_rd_index;
888 if (num < 0)
889 num += enc_num_chunks;
890 }
602 891
603static void pcmrec_dma_start(void) 892 /* no yielding, the file apis called in the codecs do that */
604{ 893 } /* end for */
605 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
606 SAR1 = (unsigned long)&PDIR2; /* Source address */
607 BCR1 = CHUNK_SIZE; /* Bytes to transfer */
608 894
609 /* Start the DMA transfer.. */ 895 /* sync file */
610#ifdef HAVE_SPDIF_IN 896 if (rec_fdata.rec_file >= 0)
611 INTERRUPTCLEAR = 0x03c00000; 897 fsync(rec_fdata.rec_file);
612#endif 898
899 cpu_boost_id(false, CPUBOOSTID_PCMRECORD);
613 900
614 /* 16Byte transfers prevents from sporadic errors during cpu_boost() */ 901 if (prio != -1)
615 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_DSIZE(3) | DMA_START; 902 {
903 /* return to original priority */
904 logf("pcmrec: unboost priority");
905 thread_set_priority(NULL, prio);
906 }
616 907
617 logf("dma1 started"); 908 last_flush_tick = current_tick; /* save tick when we left */
618} 909 logf("done");
910} /* pcmrec_flush */
619 911
620/* DMA1 Interrupt is called when the DMA has finished transfering a chunk */ 912/**
621void DMA1(void) __attribute__ ((interrupt_handler, section(".icode"))); 913 * Marks a new stream in the buffer and gives the encoder a chance for special
622void DMA1(void) 914 * handling of transition from one to the next. The encoder may change the
915 * chunk that ends the old stream by requesting more chunks and similiarly for
916 * the new but must always advance the position though the interface. It can
917 * later reject any data it cares to when writing the file but should mark the
918 * chunk so it can recognize this. ENC_WRITE_CHUNK event must be able to accept
919 * a NULL data pointer without error as well.
920 */
921static void pcmrec_new_stream(const char *filename, /* next file name */
922 unsigned long flags, /* CHUNKF_* flags */
923 int pre_index) /* index for prerecorded data */
623{ 924{
624 int res = DSR1; 925 logf("pcmrec_new_stream");
625 926
626 DSR1 = 1; /* Clear interrupt */ 927 struct enc_buffer_event_data data;
928 bool (*fnq_add_fn)(const char *) = NULL;
929 struct enc_chunk_hdr *start = NULL;
627 930
628 if (res & 0x70) 931 int get_chunk_index(struct enc_chunk_hdr *chunk)
629 { 932 {
630 DCR1 = 0; /* Stop DMA transfer */ 933 return ((char *)chunk - (char *)enc_buffer) / enc_chunk_size;
631 error_count++; 934 }
632
633 logf("dma1 err: 0x%x", res);
634
635 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
636 BCR1 = CHUNK_SIZE;
637 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
638 935
639 /* Flush recorded data to disk and stop recording */ 936 struct enc_chunk_hdr * get_prev_chunk(int index)
640 queue_post(&pcmrec_queue, PCMREC_STOP, NULL);
641 }
642#ifdef HAVE_SPDIF_IN
643 else if ((rec_source == AUDIO_SRC_SPDIF) &&
644 (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */
645 { 937 {
646 INTERRUPTCLEAR = 0x03c00000; 938 DEC_ENC_INDEX(index);
647 error_count++; 939 return GET_ENC_CHUNK(index);
940 }
648 941
649 logf("spdif err"); 942 data.pre_chunk = NULL;
943 data.chunk = GET_ENC_CHUNK(enc_wr_index);
650 944
651 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */ 945 /* end chunk */
652 BCR1 = CHUNK_SIZE; 946 if (flags & CHUNKF_END_FILE)
653 }
654#endif
655 else
656 { 947 {
657 long peak_l, peak_r; 948 data.chunk->flags &= CHUNKF_START_FILE | CHUNKF_END_FILE;
658 long *ptr, j;
659
660 ptr = GET_CHUNK(write_pos);
661 949
662 if (!is_paused) /* advance write position */ 950 if (data.chunk->flags & CHUNKF_START_FILE)
663 write_pos = (write_pos + CHUNK_SIZE) & CHUNK_MASK; 951 {
952 /* cannot start and end on same unprocessed chunk */
953 logf("file end on start");
954 flags &= ~CHUNKF_END_FILE;
955 }
956 else if (enc_rd_index == enc_wr_index)
957 {
958 /* all data flushed but file not ended - chunk will be left
959 empty */
960 logf("end on dead end");
961 data.chunk->flags = 0;
962 data.chunk->enc_size = 0;
963 data.chunk->num_pcm = 0;
964 data.chunk->enc_data = NULL;
965 INC_ENC_INDEX(enc_wr_index);
966 data.chunk = GET_ENC_CHUNK(enc_wr_index);
967 }
968 else
969 {
970 struct enc_chunk_hdr *last = get_prev_chunk(enc_wr_index);
664 971
665 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */ 972 if (last->flags & CHUNKF_END_FILE)
666 BCR1 = CHUNK_SIZE; 973 {
974 /* end already processed and marked - can't end twice */
975 logf("file end again");
976 flags &= ~CHUNKF_END_FILE;
977 }
978 }
979 }
667 980
668 peak_l = peak_r = 0; 981 /* start chunk */
982 if (flags & CHUNKF_START_FILE)
983 {
984 bool pre = flags & CHUNKF_PRERECORD;
669 985
670 /* only peak every 4th sample */ 986 if (pre)
671 for (j=0; j<CHUNK_SIZE/4; j+=4)
672 { 987 {
673 long value = ptr[j]; 988 logf("stream prerecord start");
674#ifdef ROCKBOX_BIG_ENDIAN 989 start = data.pre_chunk = GET_ENC_CHUNK(pre_index);
675 if (value > peak_l) peak_l = value; 990 start->flags &= CHUNKF_START_FILE | CHUNKF_PRERECORD;
676 else if (-value > peak_l) peak_l = -value; 991 }
677 992 else
678 value <<= 16; 993 {
679 if (value > peak_r) peak_r = value; 994 logf("stream normal start");
680 else if (-value > peak_r) peak_r = -value; 995 start = data.chunk;
681#else 996 start->flags &= CHUNKF_START_FILE;
682 if (value > peak_r) peak_r = value;
683 else if (-value > peak_r) peak_r = -value;
684
685 value <<= 16;
686 if (value > peak_l) peak_l = value;
687 else if (-value > peak_l) peak_l = -value;
688#endif
689 } 997 }
690 998
691 peak_left = (int)(peak_l >> 16); 999 /* if encoder hasn't yet processed the last start - abort the start
692 peak_right = (int)(peak_r >> 16); 1000 of the previous file queued or else it will be empty and invalid */
1001 if (start->flags & CHUNKF_START_FILE)
1002 {
1003 logf("replacing fnq tail: %s", filename);
1004 fnq_add_fn = pcmrec_fnq_replace_tail;
1005 }
1006 else
1007 {
1008 logf("adding filename: %s", filename);
1009 fnq_add_fn = pcmrec_fnq_add_filename;
1010 }
693 } 1011 }
694 1012
695 IPR |= (1<<15); /* Clear pending interrupt request */ 1013 data.flags = flags;
696} 1014 enc_events_callback(ENC_REC_NEW_STREAM, &data);
697
698/* Create WAVE file and write header */
699/* Sets returns 0 if success, -1 on failure */
700static int start_wave(void)
701{
702 wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC);
703 1015
704 if (wav_file < 0) 1016 if (flags & CHUNKF_END_FILE)
705 { 1017 {
706 wav_file = -1; 1018 int i = get_chunk_index(data.chunk);
707 logf("rec: create failed: %d", wav_file); 1019 get_prev_chunk(i)->flags |= CHUNKF_END_FILE;
708 is_error = true;
709 return -1;
710 } 1020 }
711 1021
712 /* add main file header (enc_head_size=0 for encoders without) */ 1022 if (start)
713 if (enc_head_size != write(wav_file, enc_head_buffer, enc_head_size))
714 { 1023 {
715 close(wav_file); 1024 if (!(flags & CHUNKF_PRERECORD))
716 wav_file = -1; 1025 {
717 logf("rec: write failed"); 1026 /* get stats on data added to start - sort of a prerecord operation */
718 is_error = true; 1027 int i = get_chunk_index(data.chunk);
719 return -1; 1028 struct enc_chunk_hdr *chunk = data.chunk;
720 }
721 1029
722 return 0; 1030 logf("start data: %d %d", i, enc_wr_index);
723}
724 1031
725/* Update header and set correct length values */ 1032 num_rec_bytes = 0;
726static void close_wave(void) 1033 num_rec_samples = 0;
727{
728 unsigned char head[100]; /* assume maximum 100 bytes for file header */
729 int size_read;
730 1034
731 if (wav_file != -1) 1035 while (i != enc_wr_index)
732 { 1036 {
733 /* update header before closing the file (wav+wv encoder will do) */ 1037 num_rec_bytes += chunk->enc_size;
734 if (enc_set_header_callback != NULL) 1038 num_rec_samples += chunk->num_pcm;
735 { 1039 INC_ENC_INDEX(i);
736 lseek(wav_file, 0, SEEK_SET); 1040 chunk = GET_ENC_CHUNK(i);
737 /* try to read the head size (but we'll accept less) */ 1041 }
738 size_read = read(wav_file, head, sizeof(head)); 1042
1043 start->flags &= ~CHUNKF_START_FILE;
1044 start = data.chunk;
1045 }
1046
1047 start->flags |= CHUNKF_START_FILE;
739 1048
740 enc_set_header_callback(head, size_read, num_pcm_samples, true); 1049 /* flush one file out if full and adding */
741 lseek(wav_file, 0, SEEK_SET); 1050 if (fnq_add_fn == pcmrec_fnq_add_filename && pcmrec_fnq_is_full())
742 write(wav_file, head, size_read); 1051 {
1052 logf("fnq full: flushing 1");
1053 pcmrec_flush(1);
743 } 1054 }
744 close(wav_file); 1055
745 wav_file = -1; 1056 fnq_add_fn(filename);
746 } 1057 }
747} 1058} /* pcmrec_new_stream */
748 1059
749static void pcmrec_start(void) 1060/** event handlers for pcmrec thread */
1061
1062/* PCMREC_INIT */
1063static void pcmrec_init(void)
750{ 1064{
751 long max_pre_chunks, pre_ticks, max_pre_ticks; 1065 rec_fdata.rec_file = -1;
1066
1067 /* pcm FIFO */
1068 dma_lock = true;
1069 pcm_rd_pos = 0;
1070 dma_wr_pos = 0;
1071
1072 /* encoder FIFO */
1073 enc_wr_index = 0;
1074 enc_rd_index = 0;
1075
1076 /* filename queue */
1077 fnq_rd_pos = 0;
1078 fnq_wr_pos = 0;
1079
1080 /* stats */
1081 num_rec_bytes = 0;
1082 num_rec_samples = 0;
1083 accum_rec_bytes = 0;
1084 accum_pcm_samples = 0;
1085
1086 pcm_thread_unsignal_event(PCMREC_CLOSE);
1087 is_recording = false;
1088 is_paused = false;
1089 is_stopping = false;
1090 is_error = false;
1091
1092 pcm_buffer = audio_get_recording_buffer(&rec_buffer_size);
1093 /* Line align pcm_buffer 2^4=16 bytes */
1094 pcm_buffer = (unsigned char *)ALIGN_UP_P2((unsigned)pcm_buffer, 4);
1095 enc_buffer = pcm_buffer + ALIGN_UP_P2(PCM_NUM_CHUNKS*PCM_CHUNK_SIZE +
1096 PCM_MAX_FEED_SIZE, 2);
1097
1098 pcm_init_recording();
1099 pcm_thread_signal_event(PCMREC_INIT);
1100} /* pcmrec_init */
1101
1102/* PCMREC_CLOSE */
1103static void pcmrec_close(void)
1104{
1105 dma_lock = true;
1106 pcm_close_recording();
1107 pcm_thread_unsignal_event(PCMREC_INIT);
1108 pcm_thread_signal_event(PCMREC_CLOSE);
1109} /* pcmrec_close */
1110
1111/* PCMREC_START */
1112static void pcmrec_start(const char *filename)
1113{
1114 unsigned long pre_sample_ticks;
1115 int rd_start;
752 1116
753 logf("pcmrec_start"); 1117 logf("pcmrec_start: %s", filename);
754 1118
755 if (is_recording) 1119 if (is_recording)
756 { 1120 {
757 logf("already recording"); 1121 logf("already recording");
758 record_done = true; 1122 goto already_recording;
759 return;
760 } 1123 }
761 1124
762 if (wav_file != -1) 1125 /* reset stats */
763 close_wave(); 1126 num_rec_bytes = 0;
1127 num_rec_samples = 0;
1128 accum_rec_bytes = 0;
1129 accum_pcm_samples = 0;
1130 spinup_time = -1;
1131
1132 rd_start = enc_wr_index;
1133 pre_sample_ticks = 0;
764 1134
765 if (start_wave() != 0) 1135 if (pre_record_ticks)
766 { 1136 {
767 /* failed to create the file */ 1137 int i;
768 record_done = true;
769 return;
770 }
771 1138
772 /* calculate maximum available chunks & resulting ticks */ 1139 /* calculate number of available chunks */
773 max_pre_chunks = (enc_wr_index - enc_rd_index + 1140 unsigned long avail_pre_chunks = (enc_wr_index - enc_rd_index +
774 enc_num_chunks) % enc_num_chunks;
775 if (max_pre_chunks > enc_num_chunks - WRITE_THRESHOLD)
776 max_pre_chunks = enc_num_chunks - WRITE_THRESHOLD;
777 max_pre_ticks = max_pre_chunks * HZ * enc_samp_per_chunk / 44100;
778
779 /* limit prerecord if not enough data available */
780 pre_ticks = pre_record_ticks > max_pre_ticks ?
781 max_pre_ticks : pre_record_ticks;
782 max_pre_chunks = 44100 * pre_ticks / HZ / enc_samp_per_chunk;
783 enc_rd_index = (enc_wr_index - max_pre_chunks +
784 enc_num_chunks) % enc_num_chunks; 1141 enc_num_chunks) % enc_num_chunks;
1142 /* overflow at 974 seconds of prerecording at 44.1kHz */
1143 unsigned long pre_record_sample_ticks = enc_sample_rate*pre_record_ticks;
1144
1145 /* Get exact measure of recorded data as number of samples aren't
1146 nescessarily going to be the max for each chunk */
1147 for (i = rd_start; avail_pre_chunks-- > 0;)
1148 {
1149 struct enc_chunk_hdr *chunk;
1150 unsigned long chunk_sample_ticks;
1151
1152 DEC_ENC_INDEX(i);
1153
1154 chunk = GET_ENC_CHUNK(i);
1155
1156 /* must have data to be counted */
1157 if (chunk->enc_data == NULL)
1158 continue;
785 1159
786 record_start_time = current_tick - pre_ticks; 1160 chunk_sample_ticks = chunk->num_pcm*HZ;
787 1161
788 num_rec_bytes = enc_num_chunks * CHUNK_SIZE; 1162 rd_start = i;
789 num_file_bytes = 0; 1163 pre_sample_ticks += chunk_sample_ticks;
790 num_pcm_samples = 0; 1164 num_rec_bytes += chunk->enc_size;
791 pause_start_time = 0; 1165 num_rec_samples += chunk->num_pcm;
1166
1167 /* stop here if enough already */
1168 if (pre_sample_ticks >= pre_record_sample_ticks)
1169 break;
1170 }
1171
1172 accum_rec_bytes = num_rec_bytes;
1173 accum_pcm_samples = num_rec_samples;
1174 }
1175
1176 enc_rd_index = rd_start;
1177
1178 /* filename queue should be empty */
1179 if (!pcmrec_fnq_is_empty())
1180 {
1181 logf("fnq: not empty!");
1182 pcmrec_fnq_set_empty();
1183 }
792 1184
1185 dma_lock = false;
793 is_paused = false; 1186 is_paused = false;
794 is_recording = true; 1187 is_recording = true;
795 record_done = true;
796}
797 1188
1189 pcmrec_new_stream(filename,
1190 CHUNKF_START_FILE |
1191 (pre_sample_ticks > 0 ? CHUNKF_PRERECORD : 0),
1192 enc_rd_index);
1193
1194already_recording:
1195 pcm_thread_signal_event(PCMREC_START);
1196 logf("pcmrec_start done");
1197} /* pcmrec_start */
1198
1199/* PCMREC_STOP */
798static void pcmrec_stop(void) 1200static void pcmrec_stop(void)
799{ 1201{
800 logf("pcmrec_stop"); 1202 logf("pcmrec_stop");
801 1203
802 if (is_recording) 1204 if (!is_recording)
803 { 1205 {
804 /* wait for encoding finish */ 1206 logf("not recording");
805 is_paused = true; 1207 goto not_recording_or_stopping;
806 while(!wav_queue_empty) 1208 }
807 sleep_thread(1); 1209 else if (is_stopping)
808 1210 {
809 is_recording = false; 1211 logf("already stopping");
810 1212 goto not_recording_or_stopping;
811 /* Flush buffers to file */
812 pcmrec_callback(true);
813 close_wave();
814 } 1213 }
815 1214
816 is_paused = false; 1215 is_stopping = true;
817 stop_done = true; 1216 dma_lock = true; /* lock dma write position */
1217 queue_post(&pcmrec_queue, PCMREC_FINISH_STOP, NULL);
818 1218
1219not_recording_or_stopping:
1220 pcm_thread_signal_event(PCMREC_STOP);
819 logf("pcmrec_stop done"); 1221 logf("pcmrec_stop done");
820} 1222} /* pcmrec_stop */
821 1223
822static void pcmrec_new_file(void) 1224/* PCMREC_FINISH_STOP */
1225static void pcmrec_finish_stop(void)
823{ 1226{
824 logf("pcmrec_new_file"); 1227 logf("pcmrec_finish_stop");
825 1228
826 if (!is_recording) 1229 if (!is_stopping)
827 { 1230 {
828 logf("not recording"); 1231 logf("not stopping");
829 new_file_done = true; 1232 goto not_stopping;
830 return;
831 } 1233 }
832 1234
833 /* Since pcmrec_callback() blocks until the data has been written, 1235 /* flush all available data first to avoid overflow while waiting
834 here is a good approximation when recording to the new file starts 1236 for encoding to finish */
835 */ 1237 pcmrec_flush(-1);
836 record_start_time = current_tick;
837 1238
838 if (is_paused) 1239 /* wait for encoder to finish remaining data */
839 pause_start_time = record_start_time; 1240 if (!is_error)
1241 {
1242 while (!wav_queue_empty)
1243 yield();
1244 }
840 1245
841 /* Flush what we got in buffers to file */ 1246 /* end stream at last data */
842 pcmrec_callback(true); 1247 pcmrec_new_stream(NULL, CHUNKF_END_FILE, 0);
843 1248
844 close_wave(); 1249 /* flush anything else encoder added */
845 1250 pcmrec_flush(-1);
846 num_rec_bytes = 0; 1251
847 num_file_bytes = 0; 1252 /* remove any pending file start not yet processed - should be at
848 num_pcm_samples = 0; 1253 most one at enc_wr_index */
1254 pcmrec_fnq_get_filename(NULL);
1255 /* encoder should abort any chunk it was in midst of processing */
1256 GET_ENC_CHUNK(enc_wr_index)->flags = CHUNKF_ABORT;
849 1257
850 /* start the new file */ 1258 /* filename queue should be empty */
851 if (start_wave() != 0) 1259 if (!pcmrec_fnq_is_empty())
852 { 1260 {
853 logf("new_file failed"); 1261 logf("fnq: not empty!");
854 pcmrec_stop(); 1262 pcmrec_fnq_set_empty();
855 } 1263 }
856 1264
857 new_file_done = true; 1265 /* be absolutely sure the file is closed */
858 logf("pcmrec_new_file done"); 1266 if (is_error)
859} 1267 pcmrec_close_file(&rec_fdata.rec_file);
1268 rec_fdata.rec_file = -1;
1269
1270 is_recording = false;
1271 is_paused = false;
1272 is_stopping = false;
1273 dma_lock = pre_record_ticks == 0;
1274
1275not_stopping:
1276 logf("pcmrec_finish_stop done");
1277} /* pcmrec_finish_stop */
860 1278
1279/* PCMREC_PAUSE */
861static void pcmrec_pause(void) 1280static void pcmrec_pause(void)
862{ 1281{
863 logf("pcmrec_pause"); 1282 logf("pcmrec_pause");
864 1283
865 if (!is_recording) 1284 if (!is_recording)
866 { 1285 {
867 logf("pause: not recording"); 1286 logf("not recording");
868 pause_done = true; 1287 goto not_recording_or_paused;
869 return; 1288 }
1289 else if (is_paused)
1290 {
1291 logf("already paused");
1292 goto not_recording_or_paused;
870 } 1293 }
871 1294
872 pause_start_time = current_tick; 1295 dma_lock = true; /* fix DMA write pointer at current position */
873 is_paused = true; 1296 is_paused = true;
874 pause_done = true;
875 1297
1298not_recording_or_paused:
1299 pcm_thread_signal_event(PCMREC_PAUSE);
876 logf("pcmrec_pause done"); 1300 logf("pcmrec_pause done");
877} 1301} /* pcmrec_pause */
878
879 1302
1303/* PCMREC_RESUME */
880static void pcmrec_resume(void) 1304static void pcmrec_resume(void)
881{ 1305{
882 logf("pcmrec_resume"); 1306 logf("pcmrec_resume");
883 1307
884 if (!is_paused) 1308 if (!is_recording)
885 { 1309 {
886 logf("resume: not paused"); 1310 logf("not recording");
887 resume_done = true; 1311 goto not_recording_or_not_paused;
888 return; 1312 }
1313 else if (!is_paused)
1314 {
1315 logf("not paused");
1316 goto not_recording_or_not_paused;
889 } 1317 }
890 1318
891 is_paused = false; 1319 is_paused = false;
892 is_recording = true; 1320 is_recording = true;
1321 dma_lock = false;
893 1322
894 /* Compensate for the time we have been paused */ 1323not_recording_or_not_paused:
895 if (pause_start_time) 1324 pcm_thread_signal_event(PCMREC_RESUME);
896 {
897 record_start_time += current_tick - pause_start_time;
898 pause_start_time = 0;
899 }
900
901 resume_done = true;
902 logf("pcmrec_resume done"); 1325 logf("pcmrec_resume done");
903} 1326} /* pcmrec_resume */
904 1327
905/** 1328/* PCMREC_NEW_FILE */
906 * audio_init_recording calls this function using PCMREC_INIT 1329static void pcmrec_new_file(const char *filename)
907 *
908 */
909static void pcmrec_init(void)
910{ 1330{
911 wav_file = -1; 1331 logf("pcmrec_new_file: %s", filename);
912 read_pos = 0;
913 write_pos = 0;
914 enc_wr_index = 0;
915 enc_rd_index = 0;
916 1332
917 avrg_bit_rate = 0; 1333 if (!is_recording)
918 curr_bit_rate = 0; 1334 {
919 curr_chunk_cnt = 0; 1335 logf("not recording");
920 1336 goto not_recording;
921 peak_left = 0; 1337 }
922 peak_right = 0;
923 1338
924 num_rec_bytes = 0; 1339 num_rec_bytes = 0;
925 num_file_bytes = 0; 1340 num_rec_samples = 0;
926 num_pcm_samples = 0;
927 record_start_time = 0;
928 pause_start_time = 0;
929
930 close_done = false;
931 is_recording = false;
932 is_paused = false;
933 is_error = false;
934
935 rec_buffer = (unsigned char*)(((long)audiobuf + 15) & ~15);
936 enc_buffer = rec_buffer + NUM_CHUNKS * CHUNK_SIZE + MAX_FEED_SIZE;
937 /* 8000Bytes at audiobufend */
938 enc_buffer_size = audiobufend - enc_buffer - 8000;
939
940 SET_IIS_PLAY(0x800); /* Stop any playback */
941 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
942 DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo */
943
944 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */
945 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
946 DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2;
947 ICR7 = 0x1c; /* Enable interrupt at level 7, priority 0 */
948 IMR &= ~(1<<15); /* bit 15 is DMA1 */
949
950#ifdef HAVE_SPDIF_IN
951 PHASECONFIG = 0x34; /* Gain = 3*2^13, source = EBUIN */
952#endif
953 pcmrec_dma_start();
954
955 init_done = 1;
956}
957 1341
958static void pcmrec_close(void) 1342 pcmrec_new_stream(filename,
959{ 1343 CHUNKF_START_FILE | CHUNKF_END_FILE,
960 DMAROUTE = (DMAROUTE & 0xffff00ff); 1344 0);
961 ICR7 = 0x00; /* Disable interrupt */
962 IMR |= (1<<15); /* bit 15 is DMA1 */
963 1345
964 pcmrec_dma_stop(); 1346not_recording:
965 1347 pcm_thread_signal_event(PCMREC_NEW_FILE);
966 /* Reset PDIR2 data flow */ 1348 logf("pcmrec_new_file done");
967 DATAINCONTROL = 0x200; 1349} /* pcmrec_new_file */
968 close_done = true;
969 init_done = false;
970}
971 1350
1351static void pcmrec_thread(void) __attribute__((noreturn));
972static void pcmrec_thread(void) 1352static void pcmrec_thread(void)
973{ 1353{
974 struct event ev; 1354 struct event ev;
975 1355
976 logf("thread pcmrec start"); 1356 logf("thread pcmrec start");
977 1357
978 error_count = 0;
979
980 while(1) 1358 while(1)
981 { 1359 {
982 queue_wait_w_tmo(&pcmrec_queue, &ev, HZ / 4); 1360 if (is_recording)
1361 {
1362 /* Poll periodically to flush data */
1363 queue_wait_w_tmo(&pcmrec_queue, &ev, HZ/5);
1364
1365 if (ev.id == SYS_TIMEOUT)
1366 {
1367 pcmrec_flush(0); /* flush if getting full */
1368 continue;
1369 }
1370 }
1371 else
1372 {
1373 /* Not doing anything - sit and wait for commands */
1374 queue_wait(&pcmrec_queue, &ev);
1375 }
983 1376
984 switch (ev.id) 1377 switch (ev.id)
985 { 1378 {
@@ -992,13 +1385,17 @@ static void pcmrec_thread(void)
992 break; 1385 break;
993 1386
994 case PCMREC_START: 1387 case PCMREC_START:
995 pcmrec_start(); 1388 pcmrec_start((const char *)ev.data);
996 break; 1389 break;
997 1390
998 case PCMREC_STOP: 1391 case PCMREC_STOP:
999 pcmrec_stop(); 1392 pcmrec_stop();
1000 break; 1393 break;
1001 1394
1395 case PCMREC_FINISH_STOP:
1396 pcmrec_finish_stop();
1397 break;
1398
1002 case PCMREC_PAUSE: 1399 case PCMREC_PAUSE:
1003 pcmrec_pause(); 1400 pcmrec_pause();
1004 break; 1401 break;
@@ -1008,11 +1405,11 @@ static void pcmrec_thread(void)
1008 break; 1405 break;
1009 1406
1010 case PCMREC_NEW_FILE: 1407 case PCMREC_NEW_FILE:
1011 pcmrec_new_file(); 1408 pcmrec_new_file((const char *)ev.data);
1012 break; 1409 break;
1013 1410
1014 case SYS_TIMEOUT: 1411 case PCMREC_FLUSH_NUM:
1015 pcmrec_callback(false); 1412 pcmrec_flush((unsigned)ev.data);
1016 break; 1413 break;
1017 1414
1018 case SYS_USB_CONNECTED: 1415 case SYS_USB_CONNECTED:
@@ -1023,140 +1420,267 @@ static void pcmrec_thread(void)
1023 usb_wait_for_disconnect(&pcmrec_queue); 1420 usb_wait_for_disconnect(&pcmrec_queue);
1024 } 1421 }
1025 break; 1422 break;
1026 } 1423 } /* end switch */
1027 } 1424 } /* end while */
1425} /* pcmrec_thread */
1028 1426
1029 logf("thread pcmrec done"); 1427/****************************************************************************/
1030} 1428/* */
1429/* following functions will be called by the encoder codec */
1430/* */
1431/****************************************************************************/
1031 1432
1032/* Select VINL & VINR source: 0=Line-in, 1=FM Radio */ 1433/* pass the encoder settings to the encoder */
1033void pcm_rec_mux(int source) 1434void enc_get_inputs(struct enc_inputs *inputs)
1034{ 1435{
1035#ifdef IRIVER_H300_SERIES 1436 inputs->sample_rate = sample_rate;
1036 if(source == 0) 1437 inputs->num_channels = num_channels;
1037 and_l(~0x40000000, &GPIO_OUT); /* Line In */ 1438 inputs->config = &enc_config;
1038 else 1439} /* enc_get_inputs */
1039 or_l(0x40000000, &GPIO_OUT); /* FM radio */
1040 1440
1041 or_l(0x40000000, &GPIO_ENABLE); 1441/* set the encoder dimensions (called by encoder codec at initialization and
1042 or_l(0x40000000, &GPIO_FUNCTION); 1442 termination) */
1043#elif defined(IRIVER_H100_SERIES) 1443void enc_set_parameters(struct enc_parameters *params)
1044 if(source == 0) 1444{
1045 and_l(~0x00800000, &GPIO_OUT); /* Line In */ 1445 size_t bufsize, resbytes;
1046 else
1047 or_l(0x00800000, &GPIO_OUT); /* FM radio */
1048 1446
1049 or_l(0x00800000, &GPIO_ENABLE); 1447 logf("enc_set_parameters");
1050 or_l(0x00800000, &GPIO_FUNCTION);
1051 1448
1052#elif defined(IAUDIO_X5) 1449 if (!params)
1053 if(source == 0) 1450 {
1054 or_l((1<<29), &GPIO_OUT); /* Line In */ 1451 logf("reset");
1055 else 1452 /* Encoder is terminating */
1056 and_l(~(1<<29), &GPIO_OUT); /* FM radio */ 1453 memset(&enc_config, 0, sizeof (enc_config));
1454 enc_sample_rate = 0;
1455 return;
1456 }
1457
1458 enc_sample_rate = params->enc_sample_rate;
1459 logf("enc sampr:%d", enc_sample_rate);
1460
1461 pcm_rd_pos = dma_wr_pos;
1462
1463 enc_config.afmt = params->afmt;
1464 /* addition of the header is always implied - chunk size 4-byte aligned */
1465 enc_chunk_size =
1466 ALIGN_UP_P2(ENC_CHUNK_HDR_SIZE + params->chunk_size, 2);
1467 enc_data_size = enc_chunk_size - ENC_CHUNK_HDR_SIZE;
1468 enc_events_callback = params->events_callback;
1469
1470 logf("chunk size:%d", enc_chunk_size);
1471
1472 /*** Configure the buffers ***/
1473
1474 /* Layout of recording buffer:
1475 * [ax] = possible alignment x multiple
1476 * [sx] = possible size alignment of x multiple
1477 * |[a16]|[s4]:PCM Buffer+PCM Guard|[s4 each]:Encoder Chunks|->
1478 * |[[s4]:Reserved Bytes]|Filename Queue->|[space]|
1479 */
1480 resbytes = ALIGN_UP_P2(params->reserve_bytes, 2);
1481 logf("resbytes:%d", resbytes);
1482
1483 bufsize = rec_buffer_size - (enc_buffer - pcm_buffer) -
1484 resbytes - FNQ_MIN_NUM_PATHS*MAX_PATH;
1485
1486 enc_num_chunks = bufsize / enc_chunk_size;
1487 logf("num chunks:%d", enc_num_chunks);
1057 1488
1058 or_l((1<<29), &GPIO_ENABLE); 1489 /* get real amount used by encoder chunks */
1059 or_l((1<<29), &GPIO_FUNCTION); 1490 bufsize = enc_num_chunks*enc_chunk_size;
1491 logf("enc size:%d", bufsize);
1492
1493 /* panic boost thread priority at 1 second remaining */
1494 panic_threshold = enc_num_chunks -
1495 (4*sample_rate + (enc_chunk_size-1)) / enc_chunk_size;
1496 if (panic_threshold < 0)
1497 panic_threshold = 0;
1498
1499 logf("panic thr:%d", panic_threshold);
1500
1501 /** set OUT parameters **/
1502 params->enc_buffer = enc_buffer;
1503 params->buf_chunk_size = enc_chunk_size;
1504 params->num_chunks = enc_num_chunks;
1505
1506 /* calculate reserve buffer start and return pointer to encoder */
1507 params->reserve_buffer = NULL;
1508 if (resbytes > 0)
1509 {
1510 params->reserve_buffer = enc_buffer + bufsize;
1511 bufsize += resbytes;
1512 }
1060 1513
1061 /* iAudio x5 */ 1514 /* place filename queue at end of buffer using up whatever remains */
1515 fnq_rd_pos = 0; /* reset */
1516 fnq_wr_pos = 0; /* reset */
1517 fn_queue = enc_buffer + bufsize;
1518 fnq_size = pcm_buffer + rec_buffer_size - fn_queue;
1519 fnq_size = ALIGN_DOWN(fnq_size, MAX_PATH);
1520 logf("fnq files: %d", fnq_size / MAX_PATH);
1521
1522#if 0
1523 logf("ab :%08X", (unsigned long)audiobuf);
1524 logf("pcm:%08X", (unsigned long)pcm_buffer);
1525 logf("enc:%08X", (unsigned long)enc_buffer);
1526 logf("res:%08X", (unsigned long)params->reserve_buffer);
1527 logf("fnq:%08X", (unsigned long)fn_queue);
1528 logf("end:%08X", (unsigned long)fn_queue + fnq_size);
1529 logf("abe:%08X", (unsigned long)audiobufend);
1062#endif 1530#endif
1063}
1064 1531
1532 /* init all chunk headers and reset indexes */
1533 enc_rd_index = 0;
1534 for (enc_wr_index = enc_num_chunks; enc_wr_index > 0; )
1535 GET_ENC_CHUNK(--enc_wr_index)->flags = 0;
1065 1536
1066/****************************************************************************/ 1537 logf("enc_set_parameters done");
1067/* */ 1538} /* enc_set_parameters */
1068/* following functions will be called by the encoder codec */
1069/* */
1070/****************************************************************************/
1071 1539
1072/* pass the encoder buffer pointer/size, mono/stereo, quality to the encoder */ 1540/* return encoder chunk at current write position */
1073void enc_get_inputs(int *buffer_size, int *channels, int *quality) 1541struct enc_chunk_hdr * enc_get_chunk(void)
1074{ 1542{
1075 *buffer_size = enc_buffer_size; 1543 struct enc_chunk_hdr *chunk = GET_ENC_CHUNK(enc_wr_index);
1076 *channels = enc_channels; 1544 chunk->flags &= CHUNKF_START_FILE;
1077 *quality = enc_quality;
1078}
1079 1545
1080/* set the encoder dimensions (called by encoder codec at initialization) */ 1546 if (!is_recording)
1081void enc_set_parameters(int chunk_size, int num_chunks, int samp_per_chunk, 1547 chunk->flags |= CHUNKF_PRERECORD;
1082 char *head_ptr, int head_size, int enc_id)
1083{
1084 /* set read_pos just in front of current write_pos */
1085 read_pos = (write_pos - CHUNK_SIZE) & CHUNK_MASK;
1086
1087 enc_rd_index = 0; /* reset */
1088 enc_wr_index = 0; /* reset */
1089 enc_chunk_size = chunk_size; /* max chunk size */
1090 enc_num_chunks = num_chunks; /* total number of chunks */
1091 enc_samp_per_chunk = samp_per_chunk; /* pcm samples / encoderchunk */
1092 enc_head_buffer = head_ptr; /* optional file header data (wav) */
1093 enc_head_size = head_size; /* optional file header data (wav) */
1094 audio_enc_id = enc_id; /* AFMT_* id */
1095}
1096 1548
1097/* allocate encoder chunk */ 1549 return chunk;
1098unsigned int *enc_alloc_chunk(void) 1550} /* enc_get_chunk */
1099{
1100 return (unsigned int*)(enc_buffer + enc_wr_index * enc_chunk_size);
1101}
1102 1551
1103/* free previously allocated encoder chunk */ 1552/* releases the current chunk into the available chunks */
1104void enc_free_chunk(void) 1553void enc_finish_chunk(void)
1105{ 1554{
1106 unsigned long *enc_chunk; 1555 struct enc_chunk_hdr *chunk = GET_ENC_CHUNK(enc_wr_index);
1107 1556
1108 enc_chunk = GET_ENC_CHUNK(enc_wr_index); 1557 /* encoder may have set error flag or written too much data */
1109 curr_chunk_cnt++; 1558 if ((long)chunk->flags < 0 || chunk->enc_size > enc_data_size)
1110/* curr_bit_rate += *enc_chunk * 44100 * 8 / (enc_samp_per_chunk * 1000); */ 1559 {
1111 curr_bit_rate += *enc_chunk * 441 * 8 / (enc_samp_per_chunk * 10 ); 1560 is_error = true;
1112 avrg_bit_rate = (curr_bit_rate + curr_chunk_cnt / 2) / curr_chunk_cnt;
1113 1561
1114 /* advance enc_wr_index to the next chunk */ 1562#ifdef ROCKBOX_HAS_LOGF
1115 enc_wr_index = (enc_wr_index + 1) % enc_num_chunks; 1563 if (chunk->enc_size > enc_data_size)
1564 {
1565 /* illegal to scribble over next chunk */
1566 logf("finish chk ovf: %d>%d", chunk->enc_size, enc_data_size);
1567 }
1568 else
1569 {
1570 /* encoder set error flag */
1571 logf("finish chk enc error");
1572 }
1573#endif
1574 }
1575
1576 /* advance enc_wr_index to the next encoder chunk */
1577 INC_ENC_INDEX(enc_wr_index);
1116 1578
1117 /* buffer full: advance enc_rd_index (for prerecording purpose) */ 1579 if (enc_rd_index != enc_wr_index)
1118 if (enc_rd_index == enc_wr_index)
1119 { 1580 {
1120 enc_rd_index = (enc_rd_index + 1) % enc_num_chunks; 1581 num_rec_bytes += chunk->enc_size;
1582 accum_rec_bytes += chunk->enc_size;
1583 num_rec_samples += chunk->num_pcm;
1584 accum_pcm_samples += chunk->num_pcm;
1121 } 1585 }
1122} 1586 else if (is_recording) /* buffer full */
1587 {
1588 /* keep current position */
1589 logf("enc_buffer ovf");
1590 DEC_ENC_INDEX(enc_wr_index);
1591 }
1592 else
1593 {
1594 /* advance enc_rd_index for prerecording */
1595 INC_ENC_INDEX(enc_rd_index);
1596 }
1597} /* enc_finish_chunk */
1123 1598
1124/* checks near empty state on wav input buffer */ 1599/* checks near empty state on pcm input buffer */
1125int enc_wavbuf_near_empty(void) 1600int enc_pcm_buf_near_empty(void)
1126{ 1601{
1127 /* less than 1sec raw data? => unboost encoder */ 1602 /* less than 1sec raw data? => unboost encoder */
1128 if (((write_pos - read_pos) & CHUNK_MASK) < 44100*4) 1603 size_t avail = (dma_wr_pos - pcm_rd_pos) & PCM_CHUNK_MASK;
1129 return 1; 1604 return avail < (sample_rate << 2) ? 1 : 0;
1130 else 1605} /* enc_pcm_buf_near_empty */
1131 return 0;
1132}
1133 1606
1134/* passes a pointer to next chunk of unprocessed wav data */ 1607/* passes a pointer to next chunk of unprocessed wav data */
1135char *enc_get_wav_data(int size) 1608/* TODO: this really should give the actual size returned */
1609unsigned char * enc_get_pcm_data(size_t size)
1136{ 1610{
1137 char *ptr; 1611 size_t avail = (dma_wr_pos - pcm_rd_pos) & PCM_CHUNK_MASK;
1138 int avail;
1139 1612
1140 /* limit the requested pcm data size */ 1613 /* limit the requested pcm data size */
1141 if(size > MAX_FEED_SIZE) 1614 if (size > PCM_MAX_FEED_SIZE)
1142 size = MAX_FEED_SIZE; 1615 size = PCM_MAX_FEED_SIZE;
1143
1144 avail = (write_pos - read_pos) & CHUNK_MASK;
1145 1616
1146 if (avail >= size) 1617 if (avail >= size)
1147 { 1618 {
1148 ptr = rec_buffer + read_pos; 1619 unsigned char *ptr = pcm_buffer + pcm_rd_pos;
1149 read_pos = (read_pos + size) & CHUNK_MASK; 1620 pcm_rd_pos = (pcm_rd_pos + size) & PCM_CHUNK_MASK;
1150 1621
1151 /* ptr must point to continous data at wraparound position */ 1622 /* ptr must point to continous data at wraparound position */
1152 if (read_pos < size) 1623 if ((size_t)pcm_rd_pos < size)
1153 memcpy(rec_buffer + NUM_CHUNKS * CHUNK_SIZE, 1624 memcpy(pcm_buffer + PCM_NUM_CHUNKS*PCM_CHUNK_SIZE,
1154 rec_buffer, read_pos); 1625 pcm_buffer, pcm_rd_pos);
1155 1626
1156 wav_queue_empty = false; 1627 wav_queue_empty = false;
1157 return ptr; 1628 return ptr;
1158 } 1629 }
1159 1630
1631 /* not enough data available - encoder should idle */
1160 wav_queue_empty = true; 1632 wav_queue_empty = true;
1161 return NULL; 1633 return NULL;
1162} 1634} /* enc_get_pcm_data */
1635
1636/* puts some pcm data back in the queue */
1637size_t enc_unget_pcm_data(size_t size)
1638{
1639 /* can't let DMA advance write position when doing this */
1640 int level = set_irq_level(HIGHEST_IRQ_LEVEL);
1641
1642 if (pcm_rd_pos != dma_wr_pos)
1643 {
1644 /* disallow backing up into current DMA write chunk */
1645 size_t old_avail = (pcm_rd_pos - dma_wr_pos - PCM_CHUNK_SIZE)
1646 & PCM_CHUNK_MASK;
1647
1648 /* limit size to amount of old data remaining */
1649 if (size > old_avail)
1650 size = old_avail;
1651
1652 pcm_rd_pos = (pcm_rd_pos - size) & PCM_CHUNK_MASK;
1653 }
1654
1655 set_irq_level(level);
1656
1657 return size;
1658} /* enc_unget_pcm_data */
1659
1660/** Low level pcm recording apis **/
1661
1662/****************************************************************************
1663 * Functions that do not require targeted implementation but only a targeted
1664 * interface
1665 */
1666void pcm_record_data(pcm_more_callback_type more_ready,
1667 unsigned char *start, size_t size)
1668{
1669 pcm_callback_more_ready = more_ready;
1670
1671 if (!(start && size))
1672 {
1673 size = 0;
1674 if (more_ready)
1675 more_ready(&start, &size);
1676 }
1677
1678 if (start && size)
1679 pcm_rec_dma_start(start, size);
1680} /* pcm_record_data */
1681
1682void pcm_stop_recording(void)
1683{
1684 if (pcm_recording)
1685 pcm_rec_dma_stop();
1686} /* pcm_stop_recording */
diff --git a/firmware/system.c b/firmware/system.c
index 242d84d16c..96d5f96602 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -390,8 +390,7 @@ int system_memory_guard(int newmode)
390 (void)newmode; 390 (void)newmode;
391 return 0; 391 return 0;
392} 392}
393#elif defined(CPU_COLDFIRE) 393
394/* system code is in target tree for all coldfire targets */
395#elif CONFIG_CPU == SH7034 394#elif CONFIG_CPU == SH7034
396#include "led.h" 395#include "led.h"
397#include "system.h" 396#include "system.h"
diff --git a/firmware/target/coldfire/iaudio/x5/system-x5.c b/firmware/target/coldfire/iaudio/x5/system-x5.c
index 6be6d25ce0..30a4f6e71b 100644
--- a/firmware/target/coldfire/iaudio/x5/system-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/system-x5.c
@@ -42,7 +42,7 @@ void set_cpu_frequency(long frequency)
42 PLLCR &= ~1; /* Bypass mode */ 42 PLLCR &= ~1; /* Bypass mode */
43 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 43 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
44 RECALC_DELAYS(CPUFREQ_MAX); 44 RECALC_DELAYS(CPUFREQ_MAX);
45 PLLCR = 0x13442045; 45 PLLCR = 0x03042045 | (PLLCR & 0x70C00000);
46 CSCR0 = 0x00001180; /* Flash: 4 wait states */ 46 CSCR0 = 0x00001180; /* Flash: 4 wait states */
47 CSCR1 = 0x00000980; /* LCD: 2 wait states */ 47 CSCR1 = 0x00000980; /* LCD: 2 wait states */
48 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. 48 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
@@ -60,7 +60,7 @@ void set_cpu_frequency(long frequency)
60 PLLCR &= ~1; /* Bypass mode */ 60 PLLCR &= ~1; /* Bypass mode */
61 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 61 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
62 RECALC_DELAYS(CPUFREQ_NORMAL); 62 RECALC_DELAYS(CPUFREQ_NORMAL);
63 PLLCR = 0x16430045; 63 PLLCR = 0x06030045 | (PLLCR & 0x70C00000);
64 CSCR0 = 0x00000580; /* Flash: 1 wait state */ 64 CSCR0 = 0x00000580; /* Flash: 1 wait state */
65 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 65 CSCR1 = 0x00000180; /* LCD: 0 wait states */
66 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. 66 while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked.
@@ -77,7 +77,8 @@ void set_cpu_frequency(long frequency)
77 PLLCR &= ~1; /* Bypass mode */ 77 PLLCR &= ~1; /* Bypass mode */
78 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true); 78 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
79 RECALC_DELAYS(CPUFREQ_DEFAULT); 79 RECALC_DELAYS(CPUFREQ_DEFAULT);
80 PLLCR = 0x10400200; /* Power down PLL, but keep CLSEL and CRSEL */ 80 /* Power down PLL, but keep CLSEL and CRSEL */
81 PLLCR = 0x00000200 | (PLLCR & 0x70C00000);
81 CSCR0 = 0x00000180; /* Flash: 0 wait states */ 82 CSCR0 = 0x00000180; /* Flash: 0 wait states */
82 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 83 CSCR1 = 0x00000180; /* LCD: 0 wait states */
83 DCR = (0x8000 | DEFAULT_REFRESH_TIMER); /* Refresh timer */ 84 DCR = (0x8000 | DEFAULT_REFRESH_TIMER); /* Refresh timer */
diff --git a/firmware/target/coldfire/iriver/system-iriver.c b/firmware/target/coldfire/iriver/system-iriver.c
index 3517788641..43ba4eeed4 100644
--- a/firmware/target/coldfire/iriver/system-iriver.c
+++ b/firmware/target/coldfire/iriver/system-iriver.c
@@ -81,7 +81,7 @@ void set_cpu_frequency(long frequency)
81 PLLCR &= ~1; /* Bypass mode */ 81 PLLCR &= ~1; /* Bypass mode */
82 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 82 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
83 RECALC_DELAYS(CPUFREQ_MAX); 83 RECALC_DELAYS(CPUFREQ_MAX);
84 PLLCR = 0x11c56005; 84 PLLCR = 0x01056005 | (PLLCR & 0x70c00000);
85 CSCR0 = 0x00001180; /* Flash: 4 wait states */ 85 CSCR0 = 0x00001180; /* Flash: 4 wait states */
86 CSCR1 = 0x00001580; /* LCD: 5 wait states */ 86 CSCR1 = 0x00001580; /* LCD: 5 wait states */
87#if CONFIG_USBOTG == USBOTG_ISP1362 87#if CONFIG_USBOTG == USBOTG_ISP1362
@@ -108,7 +108,7 @@ void set_cpu_frequency(long frequency)
108 PLLCR &= ~1; /* Bypass mode */ 108 PLLCR &= ~1; /* Bypass mode */
109 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false); 109 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, false);
110 RECALC_DELAYS(CPUFREQ_NORMAL); 110 RECALC_DELAYS(CPUFREQ_NORMAL);
111 PLLCR = 0x13c5e005; 111 PLLCR = 0x0305e005 | (PLLCR & 0x70c00000);
112 CSCR0 = 0x00000580; /* Flash: 1 wait state */ 112 CSCR0 = 0x00000580; /* Flash: 1 wait state */
113 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 113 CSCR1 = 0x00000180; /* LCD: 0 wait states */
114#if CONFIG_USBOTG == USBOTG_ISP1362 114#if CONFIG_USBOTG == USBOTG_ISP1362
@@ -134,7 +134,8 @@ void set_cpu_frequency(long frequency)
134 PLLCR &= ~1; /* Bypass mode */ 134 PLLCR &= ~1; /* Bypass mode */
135 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true); 135 timers_adjust_prescale(CPUFREQ_DEFAULT_MULT, true);
136 RECALC_DELAYS(CPUFREQ_DEFAULT); 136 RECALC_DELAYS(CPUFREQ_DEFAULT);
137 PLLCR = 0x10c00200; /* Power down PLL, but keep CLSEL and CRSEL */ 137 /* Power down PLL, but keep CLSEL and CRSEL */
138 PLLCR = 0x00000200 | (PLLCR & 0x70c00000);
138 CSCR0 = 0x00000180; /* Flash: 0 wait states */ 139 CSCR0 = 0x00000180; /* Flash: 0 wait states */
139 CSCR1 = 0x00000180; /* LCD: 0 wait states */ 140 CSCR1 = 0x00000180; /* LCD: 0 wait states */
140#if CONFIG_USBOTG == USBOTG_ISP1362 141#if CONFIG_USBOTG == USBOTG_ISP1362
diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c
index 66e4feb154..2fc81496db 100644
--- a/firmware/target/coldfire/system-coldfire.c
+++ b/firmware/target/coldfire/system-coldfire.c
@@ -310,3 +310,10 @@ int system_memory_guard(int newmode)
310 310
311 return oldmode; 311 return oldmode;
312} 312}
313
314/* allow setting of audio clock related bits */
315void coldfire_set_pllcr_audio_bits(long bits)
316{
317 PLLCR = (PLLCR & ~0x70c00000) | (bits & 0x70c00000);
318}
319
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index 03852115ad..24e3fb8705 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -110,6 +110,28 @@ static inline unsigned long swap32(unsigned long value)
110 return value; 110 return value;
111} 111}
112 112
113static inline unsigned long swap_odd_even32(unsigned long value)
114{
115 /*
116 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
117 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
118 */
119 unsigned long mask = 0x00FF00FF;
120
121 asm ( /* val = ABCD */
122 "and.l %[val],%[mask] \n" /* mask = .B.D */
123 "eor.l %[mask],%[val] \n" /* val = A.C. */
124 "lsl.l #8,%[mask] \n" /* mask = B.D. */
125 "lsr.l #8,%[val] \n" /* val = .A.C */
126 "or.l %[mask],%[val] \n" /* val = BADC */
127 : /* outputs */
128 [val] "+d"(value),
129 [mask]"+d"(mask)
130 );
131
132 return value;
133}
134
113static inline void invalidate_icache(void) 135static inline void invalidate_icache(void)
114{ 136{
115 asm volatile ("move.l #0x01000000,%d0\n" 137 asm volatile ("move.l #0x01000000,%d0\n"
@@ -118,6 +140,13 @@ static inline void invalidate_icache(void)
118 "movec.l %d0,%cacr"); 140 "movec.l %d0,%cacr");
119} 141}
120 142
143#ifdef IAUDIO_X5
144#define DEFAULT_PLLCR_AUDIO_BITS 0x10400000
145#else
146#define DEFAULT_PLLCR_AUDIO_BITS 0x10c00000
147#endif
148void coldfire_set_pllcr_audio_bits(long bits);
149
121/* 11.2896 MHz */ 150/* 11.2896 MHz */
122#define CPUFREQ_DEFAULT_MULT 1 151#define CPUFREQ_DEFAULT_MULT 1
123#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ) 152#define CPUFREQ_DEFAULT (CPUFREQ_DEFAULT_MULT * CPU_FREQ)
diff --git a/firmware/thread.c b/firmware/thread.c
index 6a94a52333..4094877742 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -711,6 +711,14 @@ int thread_set_priority(struct thread_entry *thread, int priority)
711 711
712 return old_priority; 712 return old_priority;
713} 713}
714
715int thread_get_priority(struct thread_entry *thread)
716{
717 if (thread == NULL)
718 thread = cores[CURRENT_CORE].running;
719
720 return thread->priority;
721}
714#endif 722#endif
715 723
716void init_threads(void) 724void init_threads(void)
diff --git a/uisimulator/sdl/lcd-charcell.c b/uisimulator/sdl/lcd-charcell.c
index 8b93653a19..eb94ebf67f 100644
--- a/uisimulator/sdl/lcd-charcell.c
+++ b/uisimulator/sdl/lcd-charcell.c
@@ -181,7 +181,8 @@ void screen_dump(void)
181 int x, y; 181 int x, y;
182 static unsigned char line[BMP_LINESIZE]; 182 static unsigned char line[BMP_LINESIZE];
183 183
184 create_numbered_filename(filename, "", "dump_", ".bmp", 4); 184 create_numbered_filename(filename, "", "dump_", ".bmp", 4,
185 IF_CNFN_NUM_(, NULL));
185 DEBUGF("screen_dump\n"); 186 DEBUGF("screen_dump\n");
186 187
187 fd = sim_creat(filename, O_WRONLY); 188 fd = sim_creat(filename, O_WRONLY);