summaryrefslogtreecommitdiff
path: root/firmware/pcm_record.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/pcm_record.c')
-rw-r--r--firmware/pcm_record.c736
1 files changed, 381 insertions, 355 deletions
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index fee2bbd35b..4e4d5f25a0 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -50,6 +50,8 @@
50#include "lcd.h" 50#include "lcd.h"
51#include "lcd-remote.h" 51#include "lcd-remote.h"
52#include "pcm_playback.h" 52#include "pcm_playback.h"
53#include "sound.h"
54#include "id3.h"
53#include "pcm_record.h" 55#include "pcm_record.h"
54 56
55extern int boost_counter; /* used for boost check */ 57extern int boost_counter; /* used for boost check */
@@ -57,43 +59,26 @@ extern int boost_counter; /* used for boost check */
57/***************************************************************************/ 59/***************************************************************************/
58 60
59static bool is_recording; /* We are recording */ 61static bool is_recording; /* We are recording */
60static bool is_stopping; /* Are we going to stop */
61static bool is_paused; /* We have paused */ 62static bool is_paused; /* We have paused */
62static bool is_error; /* An error has occured */ 63static bool is_error; /* An error has occured */
63 64
64static unsigned long num_rec_bytes; /* Num bytes recorded */ 65static unsigned long num_rec_bytes; /* Num bytes recorded */
65static unsigned long num_file_bytes; /* Num bytes written to current file */ 66static unsigned long num_file_bytes; /* Num bytes written to current file */
66static int error_count; /* Number of DMA errors */ 67static int error_count; /* Number of DMA errors */
68static unsigned long num_pcm_samples; /* Num pcm samples written to current file */
67 69
68static long record_start_time; /* Value of current_tick when recording was started */ 70static long record_start_time; /* current_tick when recording was started */
69static long pause_start_time; /* Value of current_tick when pause was started */ 71static long pause_start_time; /* current_tick when pause was started */
70static volatile int buffered_chunks; /* number of valid chunks in buffer */ 72static unsigned int sample_rate; /* Sample rate at time of recording start */
71static unsigned int sample_rate; /* Sample rate at time of recording start */ 73static int rec_source; /* Current recording source */
72static int rec_source; /* Current recording source */
73 74
74static int wav_file; 75static int wav_file;
75static char recording_filename[MAX_PATH]; 76static char recording_filename[MAX_PATH];
76 77
77static bool init_done, close_done, record_done, stop_done, pause_done, resume_done, new_file_done; 78static volatile bool init_done, close_done, record_done;
79static volatile bool stop_done, pause_done, resume_done, new_file_done;
78 80
79static short peak_left, peak_right; 81static int peak_left, peak_right;
80
81/***************************************************************************/
82
83/*
84 Some estimates:
85 Normal recording rate: 44100 HZ * 4 = 176 KB/s
86 Total buffer size: 32 MB / 176 KB/s = 181s before writing to disk
87*/
88
89#define CHUNK_SIZE 8192 /* Multiple of 4 */
90#define WRITE_THRESHOLD 250 /* (2 MB) Write when this many chunks (or less) until buffer full */
91
92#define GET_CHUNK(x) (short*)(&rec_buffer[CHUNK_SIZE*(x)])
93
94static unsigned int rec_buffer_offset;
95static unsigned char *rec_buffer; /* Circular recording buffer */
96static int num_chunks; /* Number of chunks available in rec_buffer */
97 82
98#ifdef IAUDIO_X5 83#ifdef IAUDIO_X5
99#define SET_IIS_PLAY(x) IIS1CONFIG = (x); 84#define SET_IIS_PLAY(x) IIS1CONFIG = (x);
@@ -103,27 +88,71 @@ static int num_chunks; /* Number of chunks available in rec_buffer *
103#define SET_IIS_REC(x) IIS1CONFIG = (x); 88#define SET_IIS_REC(x) IIS1CONFIG = (x);
104#endif 89#endif
105 90
106/* 91/****************************************************************************
107 Overrun occures when DMA needs to write a new chunk and write_index == read_index 92 use 2 circular buffers of same size:
108 Solution to this is to optimize pcmrec_callback, use cpu_boost or save to disk 93 rec_buffer=DMA output buffer: chunks (8192 Bytes) of raw pcm audio data
109 more often. 94 enc_buffer=encoded audio buffer: storage for encoder output data
110*/ 95
111 96 Flow:
112static int write_index; /* Current chunk the DMA is writing to */ 97 1. when entering recording_screen DMA feeds the ringbuffer rec_buffer
113static int read_index; /* Oldest chunk that is not written to disk */ 98 2. if enough pcm data are available the encoder codec does encoding of pcm
114static int read2_index; /* Latest chunk that has not been converted to little endian */ 99 chunks (4-8192 Bytes) into ringbuffer enc_buffer in codec_thread
115static long pre_record_ticks; /* pre-record time expressed in ticks */ 100 3. pcmrec_callback detects enc_buffer 'near full' and writes data to disk
116static int pre_record_chunks; /* pre-record time expressed in chunks */ 101
102 Functions calls:
103 1.main: codec_load_encoder(); start the encoder
104 2.encoder: enc_get_inputs(); get encoder buffsize, mono/stereo, quality
105 3.encoder: enc_set_parameters(); set the encoder parameters (max.chunksize)
106 4.encoder: enc_get_wav_data(); get n bytes of unprocessed pcm data
107 5.encoder: enc_wavbuf_near_empty();if true: reduce cpu_boost
108 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
110 8.encoder: enc_free_chunk(); inform main about chunk process finished
111 9.encoder: repeat 4. to 8.
112 A.main: enc_set_header_callback(); create the current format header (file)
113****************************************************************************/
114#define NUM_CHUNKS 256 /* Power of 2 */
115#define CHUNK_SIZE 8192 /* Power of 2 */
116#define MAX_FEED_SIZE 20000 /* max pcm size passed to encoder */
117#define CHUNK_MASK (NUM_CHUNKS * CHUNK_SIZE - 1)
118#define WRITE_THRESHOLD (44100 * 5 / enc_samp_per_chunk) /* 5sec */
119#define GET_CHUNK(x) (long*)(&rec_buffer[x])
120#define GET_ENC_CHUNK(x) (long*)(&enc_buffer[enc_chunk_size*(x)])
121
122static int audio_enc_id; /* current encoder id */
123static unsigned char *rec_buffer; /* Circular recording buffer */
124static unsigned char *enc_buffer; /* Circular encoding buffer */
125static unsigned char *enc_head_buffer; /* encoder header buffer */
126static int enc_head_size; /* used size in header buffer */
127static int write_pos; /* Current chunk pos for DMA writing */
128static int read_pos; /* Current chunk pos for encoding */
129static long pre_record_ticks;/* pre-record time expressed in ticks */
130static int enc_wr_index; /* Current encoding chunk write index */
131static int enc_rd_index; /* Current encoding chunk read index */
132static int enc_chunk_size; /* maximum encoder chunk size */
133static int enc_num_chunks; /* number of chunks in ringbuffer */
134static int enc_buffer_size; /* encode buffer size */
135static int enc_channels; /* 1=mono 2=stereo */
136static int enc_quality; /* mp3: 64,96,128,160,192,320 kBit */
137static int enc_samp_per_chunk;/* pcm samples per encoder chunk */
138static 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
143void (*enc_set_header_callback)(void *head_buffer, int head_size,
144 int num_pcm_samples, bool is_file_header);
117 145
118/***************************************************************************/ 146/***************************************************************************/
119 147
120static struct event_queue pcmrec_queue; 148static struct event_queue pcmrec_queue;
121static long pcmrec_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; 149static long pcmrec_stack[2*DEFAULT_STACK_SIZE/sizeof(long)];
122static const char pcmrec_thread_name[] = "pcmrec"; 150static const char pcmrec_thread_name[] = "pcmrec";
123 151
124static void pcmrec_thread(void); 152static void pcmrec_thread(void);
125static void pcmrec_dma_start(void); 153static void pcmrec_dma_start(void);
126static void pcmrec_dma_stop(void); 154static void pcmrec_dma_stop(void);
155static void close_wave(void);
127 156
128/* Event IDs */ 157/* Event IDs */
129#define PCMREC_INIT 1 /* Enable recording */ 158#define PCMREC_INIT 1 /* Enable recording */
@@ -144,10 +173,16 @@ static void pcmrec_dma_stop(void);
144void pcm_rec_init(void) 173void pcm_rec_init(void)
145{ 174{
146 queue_init(&pcmrec_queue); 175 queue_init(&pcmrec_queue);
147 create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), pcmrec_thread_name); 176 create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack),
177 pcmrec_thread_name);
148} 178}
149 179
150 180
181int audio_get_encoder_id(void)
182{
183 return audio_enc_id;
184}
185
151/* Initializes recording: 186/* Initializes recording:
152 * - Set up the UDA1380/TLV320 for recording 187 * - Set up the UDA1380/TLV320 for recording
153 * - Prepare for DMA transfers 188 * - Prepare for DMA transfers
@@ -155,13 +190,14 @@ void pcm_rec_init(void)
155 190
156void audio_init_recording(unsigned int buffer_offset) 191void audio_init_recording(unsigned int buffer_offset)
157{ 192{
158 rec_buffer_offset = buffer_offset; 193 (void)buffer_offset;
194
159 init_done = false; 195 init_done = false;
160 queue_post(&pcmrec_queue, PCMREC_INIT, 0); 196 queue_post(&pcmrec_queue, PCMREC_INIT, 0);
161 197
162 while(!init_done) 198 while(!init_done)
163 sleep_thread(); 199 sleep_thread();
164 wake_up_thread(); 200 wake_up_thread();
165} 201}
166 202
167void audio_close_recording(void) 203void audio_close_recording(void)
@@ -171,7 +207,9 @@ void audio_close_recording(void)
171 207
172 while(!close_done) 208 while(!close_done)
173 sleep_thread(); 209 sleep_thread();
174 wake_up_thread(); 210 wake_up_thread();
211
212 audio_remove_encoder();
175} 213}
176 214
177unsigned long pcm_rec_status(void) 215unsigned long pcm_rec_status(void)
@@ -184,10 +222,17 @@ unsigned long pcm_rec_status(void)
184 ret |= AUDIO_STATUS_PAUSE; 222 ret |= AUDIO_STATUS_PAUSE;
185 if (is_error) 223 if (is_error)
186 ret |= AUDIO_STATUS_ERROR; 224 ret |= AUDIO_STATUS_ERROR;
225 if (!is_recording && pre_record_ticks && init_done && !close_done)
226 ret |= AUDIO_STATUS_PRERECORD;
187 227
188 return ret; 228 return ret;
189} 229}
190 230
231int pcm_rec_current_bitrate(void)
232{
233 return avrg_bit_rate;
234}
235
191unsigned long audio_recorded_time(void) 236unsigned long audio_recorded_time(void)
192{ 237{
193 if (is_recording) 238 if (is_recording)
@@ -248,6 +293,8 @@ unsigned long audio_get_spdif_sample_rate(void)
248} 293}
249#endif 294#endif
250 295
296#if 0
297/* not needed atm */
251#ifdef HAVE_SPDIF_POWER 298#ifdef HAVE_SPDIF_POWER
252static bool spdif_power_setting; 299static bool spdif_power_setting;
253 300
@@ -256,21 +303,18 @@ void audio_set_spdif_power_setting(bool on)
256 spdif_power_setting = on; 303 spdif_power_setting = on;
257} 304}
258#endif 305#endif
306#endif
259 307
260/** 308/**
261 * Sets the audio source 309 * Sets recording parameters
262 * 310 *
263 * This functions starts feeding the CPU with audio data over the I2S bus 311 * This functions starts feeding the CPU with audio data over the I2S bus
264 *
265 * @param source 0=mic, 1=line-in, 2=spdif
266 */ 312 */
267void audio_set_recording_options(int frequency, int quality, 313void audio_set_recording_options(int frequency, int quality,
268 int source, int channel_mode, 314 int source, int channel_mode,
269 bool editable, int prerecord_time) 315 bool editable, int prerecord_time)
270{ 316{
271 /* TODO: */ 317 /* TODO: */
272 (void)quality;
273 (void)channel_mode;
274 (void)editable; 318 (void)editable;
275 319
276 /* NOTE: Coldfire UDA based recording does not yet support anything other 320 /* NOTE: Coldfire UDA based recording does not yet support anything other
@@ -278,69 +322,30 @@ void audio_set_recording_options(int frequency, int quality,
278 * based recording will overwrite this value with the proper sample rate in 322 * based recording will overwrite this value with the proper sample rate in
279 * audio_record(), and will not be affected by this. 323 * audio_record(), and will not be affected by this.
280 */ 324 */
281 frequency = 44100; 325 frequency = 44100;
326 enc_quality = quality;
327 rec_source = source;
328 enc_channels = channel_mode == CHN_MODE_MONO ? 1 : 2;
282 pre_record_ticks = prerecord_time * HZ; 329 pre_record_ticks = prerecord_time * HZ;
283 pre_record_chunks = ((frequency * prerecord_time * 4)/CHUNK_SIZE)+1;
284 if(pre_record_chunks >= (num_chunks-250))
285 {
286 /* we can't prerecord more than our buffersize minus treshold to write to disk! */
287 pre_record_chunks = num_chunks-250;
288 /* don't forget to recalculate that time! */
289 pre_record_ticks = ((pre_record_chunks * CHUNK_SIZE)/(4*frequency)) * HZ;
290 }
291
292 //logf("pcmrec: src=%d", source);
293 330
294 rec_source = source;
295#ifdef HAVE_SPDIF_POWER
296 /* Check if S/PDIF output power should be switched off or on. NOTE: assumes
297 both optical in and out is controlled by the same power source, which is
298 the case on H1x0. */
299 spdif_power_enable((source == 2) || spdif_power_setting);
300#endif
301 switch (source) 331 switch (source)
302 { 332 {
303 /* mic */ 333 case AUDIO_SRC_MIC:
304 case 0: 334 case AUDIO_SRC_LINEIN:
305 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */ 335#ifdef HAVE_FMRADIO_IN
306 DATAINCONTROL = 0xc020; 336 case AUDIO_SRC_FMRADIO:
307
308#ifdef HAVE_UDA1380
309 uda1380_enable_recording(true);
310#endif 337#endif
311#ifdef HAVE_TLV320
312 tlv320_enable_recording(true);
313#endif
314 break;
315
316 /* line-in */
317 case 1:
318 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */ 338 /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */
319 DATAINCONTROL = 0xc020; 339 DATAINCONTROL = 0xc020;
320
321#ifdef HAVE_UDA1380
322 uda1380_enable_recording(false);
323#endif
324#ifdef HAVE_TLV320
325 tlv320_enable_recording(false);
326#endif
327 break; 340 break;
328#ifdef HAVE_SPDIF_IN 341
329 /* SPDIF */ 342#ifdef HAVE_SPDIF_IN
330 case 2: 343 case AUDIO_SRC_SPDIF:
331 /* Int. when 6 samples in FIFO. PDIR2 source = ebu1RcvData */ 344 /* Int. when 6 samples in FIFO. PDIR2 source = ebu1RcvData */
332 DATAINCONTROL = 0xc038; 345 DATAINCONTROL = 0xc038;
333#ifdef HAVE_SPDIF_POWER
334 EBU1CONFIG = spdif_power_setting ? (1 << 2) : 0;
335 /* Input source is EBUin1, Feed-through monitoring if desired */
336#else
337 EBU1CONFIG = (1 << 2);
338 /* Input source is EBUin1, Feed-through monitoring */
339#endif
340 uda1380_disable_recording();
341 break; 346 break;
342#endif 347#endif /* HAVE_SPDIF_IN */
343 } 348 }
344 349
345 sample_rate = frequency; 350 sample_rate = frequency;
346 351
@@ -349,7 +354,8 @@ void audio_set_recording_options(int frequency, int quality,
349 SET_IIS_PLAY(0x800); /* Reset before reprogram */ 354 SET_IIS_PLAY(0x800); /* Reset before reprogram */
350 355
351#ifdef HAVE_SPDIF_IN 356#ifdef HAVE_SPDIF_IN
352 if (source == 2) { 357 if (source == AUDIO_SRC_SPDIF)
358 {
353 /* SCLK2 = Audioclk/4 (can't use EBUin clock), TXSRC = EBU1rcv, 64 bclk/wclk */ 359 /* SCLK2 = Audioclk/4 (can't use EBUin clock), TXSRC = EBU1rcv, 64 bclk/wclk */
354 IIS2CONFIG = (6 << 12) | (7 << 8) | (4 << 2); 360 IIS2CONFIG = (6 << 12) | (7 << 8) | (4 << 2);
355 /* S/PDIF feed-through already configured */ 361 /* S/PDIF feed-through already configured */
@@ -367,6 +373,8 @@ void audio_set_recording_options(int frequency, int quality,
367 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */ 373 /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */
368 SET_IIS_PLAY( (8 << 12) | (4 << 8) | (4 << 2) ); 374 SET_IIS_PLAY( (8 << 12) | (4 << 8) | (4 << 2) );
369#endif 375#endif
376
377 audio_load_encoder(rec_quality_info_afmt[quality]);
370} 378}
371 379
372 380
@@ -380,10 +388,9 @@ void audio_set_recording_options(int frequency, int quality,
380void audio_set_recording_gain(int left, int right, int type) 388void audio_set_recording_gain(int left, int right, int type)
381{ 389{
382 //logf("rcmrec: t=%d l=%d r=%d", type, left, right); 390 //logf("rcmrec: t=%d l=%d r=%d", type, left, right);
383#ifdef HAVE_UDA1380 391#if defined(HAVE_UDA1380)
384 uda1380_set_recvol(left, right, type); 392 uda1380_set_recvol(left, right, type);
385#endif 393#elif defined (HAVE_TLV320)
386#ifdef HAVE_TLV320
387 tlv320_set_recvol(left, right, type); 394 tlv320_set_recvol(left, right, type);
388#endif 395#endif
389} 396}
@@ -406,7 +413,7 @@ void audio_record(const char *filename)
406 recording_filename[MAX_PATH - 1] = 0; 413 recording_filename[MAX_PATH - 1] = 0;
407 414
408#ifdef HAVE_SPDIF_IN 415#ifdef HAVE_SPDIF_IN
409 if (rec_source == 2) 416 if (rec_source == AUDIO_SRC_SPDIF)
410 sample_rate = audio_get_spdif_sample_rate(); 417 sample_rate = audio_get_spdif_sample_rate();
411#endif 418#endif
412 419
@@ -447,6 +454,7 @@ void audio_stop_recording(void)
447 454
448 logf("pcm_stop"); 455 logf("pcm_stop");
449 456
457 is_paused = true; /* fix pcm write ptr at current position */
450 stop_done = false; 458 stop_done = false;
451 queue_post(&pcmrec_queue, PCMREC_STOP, 0); 459 queue_post(&pcmrec_queue, PCMREC_STOP, 0);
452 460
@@ -499,9 +507,9 @@ void audio_resume_recording(void)
499void pcm_rec_get_peaks(int *left, int *right) 507void pcm_rec_get_peaks(int *left, int *right)
500{ 508{
501 if (left) 509 if (left)
502 *left = (int)peak_left; 510 *left = peak_left;
503 if (right) 511 if (right)
504 *right = (int)peak_right; 512 *right = peak_right;
505 peak_left = 0; 513 peak_left = 0;
506 peak_right = 0; 514 peak_right = 0;
507} 515}
@@ -511,7 +519,7 @@ void pcm_rec_get_peaks(int *left, int *right)
511/***************************************************************************/ 519/***************************************************************************/
512 520
513/** 521/**
514 * Process the chunks using read_index and write_index. 522 * Process the chunks
515 * 523 *
516 * This function is called when queue_get_w_tmo times out. 524 * This function is called when queue_get_w_tmo times out.
517 * 525 *
@@ -519,70 +527,24 @@ void pcm_rec_get_peaks(int *left, int *right)
519 * they want to save everything in the buffers to disk. 527 * they want to save everything in the buffers to disk.
520 * 528 *
521 */ 529 */
522
523static void pcmrec_callback(bool flush) ICODE_ATTR;
524static void pcmrec_callback(bool flush) 530static void pcmrec_callback(bool flush)
525{ 531{
526 int num_ready, num_free, num_new; 532 int i, num_ready, size_yield;
527 short *ptr; 533 long *enc_chunk, chunk_size;
528 short value;
529 int i, j, w;
530
531 w = write_index;
532
533 num_new = w - read2_index;
534 if (num_new < 0)
535 num_new += num_chunks;
536
537 for (i=0; i<num_new; i++)
538 {
539 /* Convert the samples to little-endian so we only have to write later
540 (Less hd-spinning time), also do peak detection while we're at it
541 */
542 ptr = GET_CHUNK(read2_index);
543 for (j=0; j<CHUNK_SIZE/4; j++)
544 {
545 value = *ptr;
546 if(value > peak_left)
547 peak_left = value;
548 else if (-value > peak_left)
549 peak_left = -value;
550
551 *ptr = htole16(value);
552 ptr++;
553
554 value = *ptr;
555 if(value > peak_right)
556 peak_right = value;
557 else if (-value > peak_right)
558 peak_right = -value;
559
560 *ptr = htole16(value);
561 ptr++;
562 }
563 534
564 if(is_recording && !is_paused) 535 if (!is_recording && !flush)
565 num_rec_bytes += CHUNK_SIZE;
566
567 read2_index++;
568 if (read2_index >= num_chunks)
569 read2_index = 0;
570 }
571
572 if ((!is_recording || is_paused) && !flush)
573 {
574 /* not recording = no saving to disk, fake buffer clearing */
575 read_index = write_index;
576 return; 536 return;
577 }
578 537
579 num_ready = w - read_index; 538 num_ready = enc_wr_index - enc_rd_index;
580 if (num_ready < 0) 539 if (num_ready < 0)
581 num_ready += num_chunks; 540 num_ready += enc_num_chunks;
582 541
583 num_free = num_chunks - num_ready; 542 /* calculate an estimate of recorded bytes */
584 543 num_rec_bytes = num_file_bytes + num_ready * /* enc_chunk_size */
585 if (num_free <= WRITE_THRESHOLD || flush) 544 ((avrg_bit_rate * 1000 / 8 * enc_samp_per_chunk + 22050) / 44100);
545
546 /* near full state reached: less than 5sec remaining space */
547 if (enc_num_chunks - num_ready < WRITE_THRESHOLD || flush)
586 { 548 {
587 bool must_boost = (boost_counter ? false : true); 549 bool must_boost = (boost_counter ? false : true);
588 550
@@ -591,23 +553,41 @@ static void pcmrec_callback(bool flush)
591 if(must_boost) 553 if(must_boost)
592 cpu_boost(true); 554 cpu_boost(true);
593 555
556 size_yield = 0;
594 for (i=0; i<num_ready; i++) 557 for (i=0; i<num_ready; i++)
595 { 558 {
596 if (write(wav_file, GET_CHUNK(read_index), CHUNK_SIZE) != CHUNK_SIZE) 559 enc_chunk = GET_ENC_CHUNK(enc_rd_index);
560 chunk_size = *enc_chunk++;
561
562 /* safety net: if size entry got corrupted => limit */
563 if (chunk_size > (long)(enc_chunk_size - sizeof(long)))
564 chunk_size = enc_chunk_size - sizeof(long);
565
566 if (enc_set_header_callback != NULL)
567 enc_set_header_callback(enc_chunk, enc_chunk_size,
568 num_pcm_samples, false);
569
570 if (write(wav_file, enc_chunk, chunk_size) != chunk_size)
597 { 571 {
572 close_wave();
598 if(must_boost) 573 if(must_boost)
599 cpu_boost(false); 574 cpu_boost(false);
600 logf("pcmrec: write err"); 575 logf("pcmrec: write err");
601 pcmrec_dma_stop(); 576 is_error = true;
602 return; 577 break;
603 } 578 }
604 579
605 num_file_bytes += CHUNK_SIZE; 580 num_file_bytes += chunk_size;
606 581 num_pcm_samples += enc_samp_per_chunk;
607 read_index++; 582 size_yield += chunk_size;
608 if (read_index >= num_chunks) 583
609 read_index = 0; 584 if (size_yield >= 32768)
610 yield(); 585 { /* yield when 32kB written */
586 size_yield = 0;
587 yield();
588 }
589
590 enc_rd_index = (enc_rd_index + 1) % enc_num_chunks;
611 } 591 }
612 592
613 if(must_boost) 593 if(must_boost)
@@ -623,36 +603,33 @@ static void pcmrec_callback(bool flush)
623/* Abort dma transfer */ 603/* Abort dma transfer */
624static void pcmrec_dma_stop(void) 604static void pcmrec_dma_stop(void)
625{ 605{
626 DCR1 = 0; 606 DCR1 = 0;
627 607
628 is_error = true;
629 is_recording = false;
630
631 error_count++; 608 error_count++;
632 609
610 DSR1 = 1; /* Clear interrupt */
611 IPR |= (1<<15); /* Clear pending interrupt request */
612
633 logf("dma1 stopped"); 613 logf("dma1 stopped");
634} 614}
635 615
636static void pcmrec_dma_start(void) 616static void pcmrec_dma_start(void)
637{ 617{
638 DAR1 = (unsigned long)GET_CHUNK(write_index); /* Destination address */ 618 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
639 SAR1 = (unsigned long)&PDIR2; /* Source address */ 619 SAR1 = (unsigned long)&PDIR2; /* Source address */
640 BCR1 = CHUNK_SIZE; /* Bytes to transfer */ 620 BCR1 = CHUNK_SIZE; /* Bytes to transfer */
641 621
642 /* Start the DMA transfer.. */ 622 /* Start the DMA transfer.. */
643 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
644
645#ifdef HAVE_SPDIF_IN 623#ifdef HAVE_SPDIF_IN
646 INTERRUPTCLEAR = 0x03c00000; 624 INTERRUPTCLEAR = 0x03c00000;
647#endif 625#endif
648 626
649 /* pre-recording: buffer count */ 627 /* 16Byte transfers prevents from sporadic errors during cpu_boost() */
650 buffered_chunks = 0; 628 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_DSIZE(3) | DMA_START;
651 629
652 logf("dma1 started"); 630 logf("dma1 started");
653} 631}
654 632
655
656/* DMA1 Interrupt is called when the DMA has finished transfering a chunk */ 633/* DMA1 Interrupt is called when the DMA has finished transfering a chunk */
657void DMA1(void) __attribute__ ((interrupt_handler, section(".icode"))); 634void DMA1(void) __attribute__ ((interrupt_handler, section(".icode")));
658void DMA1(void) 635void DMA1(void)
@@ -668,62 +645,64 @@ void DMA1(void)
668 645
669 logf("dma1 err: 0x%x", res); 646 logf("dma1 err: 0x%x", res);
670 647
671 DAR1 = (unsigned long)GET_CHUNK(write_index); /* Destination address */ 648 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
672 BCR1 = CHUNK_SIZE; 649 BCR1 = CHUNK_SIZE;
673 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START; 650 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
651
652 /* Flush recorded data to disk and stop recording */
653 queue_post(&pcmrec_queue, PCMREC_STOP, NULL);
674 } 654 }
675#ifdef HAVE_SPDIF_IN 655#ifdef HAVE_SPDIF_IN
676 else if ((rec_source == 2) && (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */ 656 else if ((rec_source == AUDIO_SRC_SPDIF) &&
657 (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */
677 { 658 {
678 INTERRUPTCLEAR = 0x03c00000; 659 INTERRUPTCLEAR = 0x03c00000;
679 error_count++; 660 error_count++;
680 661
681 logf("spdif err"); 662 logf("spdif err");
682 663
683 if (is_stopping) 664 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
684 { 665 BCR1 = CHUNK_SIZE;
685 DCR1 = 0; /* Stop DMA transfer */
686 is_stopping = false;
687
688 logf("dma1 stopping");
689 }
690 else
691 {
692 DAR1 = (unsigned long)GET_CHUNK(write_index); /* Destination address */
693 BCR1 = CHUNK_SIZE;
694 }
695 } 666 }
696#endif 667#endif
697 else 668 else
698 { 669 {
699 write_index++; 670 long peak_l, peak_r;
700 if (write_index >= num_chunks) 671 long *ptr, j;
701 write_index = 0;
702 672
703 /* update number of valid chunks for pre-recording */ 673 ptr = GET_CHUNK(write_pos);
704 if(buffered_chunks < num_chunks)
705 buffered_chunks++;
706 674
707 if (is_stopping) 675 if (!is_paused) /* advance write position */
708 { 676 write_pos = (write_pos + CHUNK_SIZE) & CHUNK_MASK;
709 DCR1 = 0; /* Stop DMA transfer */
710 is_stopping = false;
711 677
712 logf("dma1 stopping"); 678 DAR1 = (unsigned long)GET_CHUNK(write_pos); /* Destination address */
713 } 679 BCR1 = CHUNK_SIZE;
714 else if (write_index == read_index)
715 {
716 DCR1 = 0; /* Stop DMA transfer */
717 is_recording = false;
718 680
719 logf("dma1 overrun"); 681 peak_l = peak_r = 0;
720 682
721 } 683 /* only peak every 4th sample */
722 else 684 for (j=0; j<CHUNK_SIZE/4; j+=4)
723 { 685 {
724 DAR1 = (unsigned long)GET_CHUNK(write_index); /* Destination address */ 686 long value = ptr[j];
725 BCR1 = CHUNK_SIZE; 687#ifdef ROCKBOX_BIG_ENDIAN
688 if (value > peak_l) peak_l = value;
689 else if (-value > peak_l) peak_l = -value;
690
691 value <<= 16;
692 if (value > peak_r) peak_r = value;
693 else if (-value > peak_r) peak_r = -value;
694#else
695 if (value > peak_r) peak_r = value;
696 else if (-value > peak_r) peak_r = -value;
697
698 value <<= 16;
699 if (value > peak_l) peak_l = value;
700 else if (-value > peak_l) peak_l = -value;
701#endif
726 } 702 }
703
704 peak_left = (int)(peak_l >> 16);
705 peak_right = (int)(peak_r >> 16);
727 } 706 }
728 707
729 IPR |= (1<<15); /* Clear pending interrupt request */ 708 IPR |= (1<<15); /* Clear pending interrupt request */
@@ -733,15 +712,8 @@ void DMA1(void)
733/* Sets returns 0 if success, -1 on failure */ 712/* Sets returns 0 if success, -1 on failure */
734static int start_wave(void) 713static int start_wave(void)
735{ 714{
736 unsigned char header[44] =
737 {
738 'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',
739 0x10,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,
740 4,0,0x10,0,'d','a','t','a',0,0,0,0
741 };
742 unsigned long avg_bytes_per_sec;
743
744 wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC); 715 wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC);
716
745 if (wav_file < 0) 717 if (wav_file < 0)
746 { 718 {
747 wav_file = -1; 719 wav_file = -1;
@@ -749,19 +721,9 @@ static int start_wave(void)
749 is_error = true; 721 is_error = true;
750 return -1; 722 return -1;
751 } 723 }
752 /* Now set the sample rate field of the WAV header to what it should be */
753 header[24] = (unsigned char)(sample_rate & 0xff);
754 header[25] = (unsigned char)(sample_rate >> 8);
755 header[26] = (unsigned char)(sample_rate >> 16);
756 header[27] = (unsigned char)(sample_rate >> 24);
757 /* And then the average bytes per second field */
758 avg_bytes_per_sec = sample_rate*4; /* Hard coded to 16 bit stereo */
759 header[28] = (unsigned char)(avg_bytes_per_sec & 0xff);
760 header[29] = (unsigned char)(avg_bytes_per_sec >> 8);
761 header[30] = (unsigned char)(avg_bytes_per_sec >> 16);
762 header[31] = (unsigned char)(avg_bytes_per_sec >> 24);
763 724
764 if (sizeof(header) != write(wav_file, header, sizeof(header))) 725 /* add main file header (enc_head_size=0 for encoders without) */
726 if (enc_head_size != write(wav_file, enc_head_buffer, enc_head_size))
765 { 727 {
766 close(wav_file); 728 close(wav_file);
767 wav_file = -1; 729 wav_file = -1;
@@ -776,18 +738,22 @@ static int start_wave(void)
776/* Update header and set correct length values */ 738/* Update header and set correct length values */
777static void close_wave(void) 739static void close_wave(void)
778{ 740{
779 long l; 741 unsigned char head[100]; /* assume maximum 100 bytes for file header */
742 int size_read;
780 743
781 if (wav_file != -1) 744 if (wav_file != -1)
782 { 745 {
783 l = htole32(num_file_bytes + 36); 746 /* update header before closing the file (wav+wv encoder will do) */
784 lseek(wav_file, 4, SEEK_SET); 747 if (enc_set_header_callback != NULL)
785 write(wav_file, &l, 4); 748 {
786 749 lseek(wav_file, 0, SEEK_SET);
787 l = htole32(num_file_bytes); 750 /* try to read the head size (but we'll accept less) */
788 lseek(wav_file, 40, SEEK_SET); 751 size_read = read(wav_file, head, sizeof(head));
789 write(wav_file, &l, 4); 752
790 753 enc_set_header_callback(head, size_read, num_pcm_samples, true);
754 lseek(wav_file, 0, SEEK_SET);
755 write(wav_file, head, size_read);
756 }
791 close(wav_file); 757 close(wav_file);
792 wav_file = -1; 758 wav_file = -1;
793 } 759 }
@@ -795,8 +761,7 @@ static void close_wave(void)
795 761
796static void pcmrec_start(void) 762static void pcmrec_start(void)
797{ 763{
798 int pre_chunks = pre_record_chunks; /* recalculate every time! */ 764 long max_pre_chunks, pre_ticks, max_pre_ticks;
799 long pre_ticks = pre_record_ticks; /* recalculate every time! */
800 765
801 logf("pcmrec_start"); 766 logf("pcmrec_start");
802 767
@@ -808,7 +773,7 @@ static void pcmrec_start(void)
808 } 773 }
809 774
810 if (wav_file != -1) 775 if (wav_file != -1)
811 close(wav_file); 776 close_wave();
812 777
813 if (start_wave() != 0) 778 if (start_wave() != 0)
814 { 779 {
@@ -817,32 +782,29 @@ static void pcmrec_start(void)
817 return; 782 return;
818 } 783 }
819 784
820 /* pre-recording calculation */ 785 /* calculate maximum available chunks & resulting ticks */
821 if(buffered_chunks < pre_chunks) 786 max_pre_chunks = (enc_wr_index - enc_rd_index +
822 { 787 enc_num_chunks) % enc_num_chunks;
823 /* not enough good chunks available - limit pre-record time */ 788 if (max_pre_chunks > enc_num_chunks - WRITE_THRESHOLD)
824 pre_chunks = buffered_chunks; 789 max_pre_chunks = enc_num_chunks - WRITE_THRESHOLD;
825 pre_ticks = ((buffered_chunks * CHUNK_SIZE)/(4*sample_rate)) * HZ; 790 max_pre_ticks = max_pre_chunks * HZ * enc_samp_per_chunk / 44100;
826 }
827 record_start_time = current_tick - pre_ticks;
828 791
829 read_index = write_index - pre_chunks; 792 /* limit prerecord if not enough data available */
830 if(read_index < 0) 793 pre_ticks = pre_record_ticks > max_pre_ticks ?
831 { 794 max_pre_ticks : pre_record_ticks;
832 read_index += num_chunks; 795 max_pre_chunks = 44100 * pre_ticks / HZ / enc_samp_per_chunk;
833 } 796 enc_rd_index = (enc_wr_index - max_pre_chunks +
797 enc_num_chunks) % enc_num_chunks;
834 798
835 peak_left = 0; 799 record_start_time = current_tick - pre_ticks;
836 peak_right = 0; 800
837 801 num_rec_bytes = enc_num_chunks * CHUNK_SIZE;
838 num_rec_bytes = pre_chunks * CHUNK_SIZE;
839 num_file_bytes = 0; 802 num_file_bytes = 0;
803 num_pcm_samples = 0;
840 pause_start_time = 0; 804 pause_start_time = 0;
841 805
842 is_stopping = false;
843 is_paused = false; 806 is_paused = false;
844 is_recording = true; 807 is_recording = true;
845
846 record_done = true; 808 record_done = true;
847} 809}
848 810
@@ -850,36 +812,24 @@ static void pcmrec_stop(void)
850{ 812{
851 logf("pcmrec_stop"); 813 logf("pcmrec_stop");
852 814
853 if (!is_recording) 815 if (is_recording)
854 { 816 {
855 stop_done = true; 817 /* wait for encoding finish */
856 return; 818 is_paused = true;
857 } 819 while(!wav_queue_empty)
858
859 if (!is_paused)
860 {
861 /* wait for recording to finish */
862 is_stopping = true;
863
864 while (is_stopping && is_recording)
865 sleep_thread(); 820 sleep_thread();
866 wake_up_thread();
867
868 is_stopping = false;
869 }
870
871 is_recording = false;
872
873 /* Flush buffers to file */
874 pcmrec_callback(true);
875 821
876 close_wave(); 822 wake_up_thread();
823 is_recording = false;
877 824
825 /* Flush buffers to file */
826 pcmrec_callback(true);
827 close_wave();
828 }
829
830 is_paused = false;
878 stop_done = true; 831 stop_done = true;
879 832
880 /* Finally start dma again for peakmeters and pre-recoding to work. */
881 pcmrec_dma_start();
882
883 logf("pcmrec_stop done"); 833 logf("pcmrec_stop done");
884} 834}
885 835
@@ -898,7 +848,6 @@ static void pcmrec_new_file(void)
898 here is a good approximation when recording to the new file starts 848 here is a good approximation when recording to the new file starts
899 */ 849 */
900 record_start_time = current_tick; 850 record_start_time = current_tick;
901 num_rec_bytes = 0;
902 851
903 if (is_paused) 852 if (is_paused)
904 pause_start_time = record_start_time; 853 pause_start_time = record_start_time;
@@ -908,7 +857,9 @@ static void pcmrec_new_file(void)
908 857
909 close_wave(); 858 close_wave();
910 859
860 num_rec_bytes = 0;
911 num_file_bytes = 0; 861 num_file_bytes = 0;
862 num_pcm_samples = 0;
912 863
913 /* start the new file */ 864 /* start the new file */
914 if (start_wave() != 0) 865 if (start_wave() != 0)
@@ -932,20 +883,8 @@ static void pcmrec_pause(void)
932 return; 883 return;
933 } 884 }
934 885
935 /* Abort DMA transfer and flush to file? */
936
937 is_stopping = true;
938
939 while (is_stopping && is_recording)
940 sleep_thread();
941 wake_up_thread();
942
943 pause_start_time = current_tick; 886 pause_start_time = current_tick;
944 is_paused = true; 887 is_paused = true;
945
946 /* Flush what we got in buffers to file */
947 pcmrec_callback(true);
948
949 pause_done = true; 888 pause_done = true;
950 889
951 logf("pcmrec_pause done"); 890 logf("pcmrec_pause done");
@@ -973,10 +912,7 @@ static void pcmrec_resume(void)
973 pause_start_time = 0; 912 pause_start_time = 0;
974 } 913 }
975 914
976 pcmrec_dma_start();
977
978 resume_done = true; 915 resume_done = true;
979
980 logf("pcmrec_resume done"); 916 logf("pcmrec_resume done");
981} 917}
982 918
@@ -986,50 +922,47 @@ static void pcmrec_resume(void)
986 */ 922 */
987static void pcmrec_init(void) 923static void pcmrec_init(void)
988{ 924{
989 unsigned long buffer_size;
990
991 wav_file = -1; 925 wav_file = -1;
992 read_index = 0; 926 read_pos = 0;
993 read2_index = 0; 927 write_pos = 0;
994 write_index = 0; 928 enc_wr_index = 0;
995 pre_record_chunks = 0; 929 enc_rd_index = 0;
996 pre_record_ticks = 0; 930
931 avrg_bit_rate = 0;
932 curr_bit_rate = 0;
933 curr_chunk_cnt = 0;
997 934
998 peak_left = 0; 935 peak_left = 0;
999 peak_right = 0; 936 peak_right = 0;
1000 937
1001 num_rec_bytes = 0; 938 num_rec_bytes = 0;
1002 num_file_bytes = 0; 939 num_file_bytes = 0;
940 num_pcm_samples = 0;
1003 record_start_time = 0; 941 record_start_time = 0;
1004 pause_start_time = 0; 942 pause_start_time = 0;
1005 buffered_chunks = 0; 943
1006 944 close_done = false;
1007 is_recording = false; 945 is_recording = false;
1008 is_stopping = false;
1009 is_paused = false; 946 is_paused = false;
1010 is_error = false; 947 is_error = false;
1011 948
1012 rec_buffer = (unsigned char*)(((unsigned long)audiobuf + rec_buffer_offset) & ~3); 949 rec_buffer = (unsigned char*)(((long)audiobuf + 15) & ~15);
1013 buffer_size = (long)audiobufend - (long)audiobuf - rec_buffer_offset - 16; 950 enc_buffer = rec_buffer + NUM_CHUNKS * CHUNK_SIZE + MAX_FEED_SIZE;
1014 951 /* 8000Bytes at audiobufend */
1015 logf("buf size: %d kb", buffer_size/1024); 952 enc_buffer_size = audiobufend - enc_buffer - 8000;
1016
1017 num_chunks = buffer_size / CHUNK_SIZE;
1018
1019 logf("num_chunks: %d", num_chunks);
1020 953
1021 SET_IIS_PLAY(0x800); /* Stop any playback */ 954 SET_IIS_PLAY(0x800); /* Stop any playback */
1022 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */ 955 AUDIOGLOB |= 0x180; /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
1023 DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo */ 956 DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo */
1024 957
1025 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */ 958 DIVR1 = 55; /* DMA1 is mapped into vector 55 in system.c */
1026 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */ 959 DMACONFIG = 1; /* DMA0Req = PDOR3, DMA1Req = PDIR2 */
1027 DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2; 960 DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2;
1028 ICR7 = 0x1c; /* Enable interrupt at level 7, priority 0 */ 961 ICR7 = 0x1c; /* Enable interrupt at level 7, priority 0 */
1029 IMR &= ~(1<<15); /* bit 15 is DMA1 */ 962 IMR &= ~(1<<15); /* bit 15 is DMA1 */
1030 963
1031#ifdef HAVE_SPDIF_IN 964#ifdef HAVE_SPDIF_IN
1032 PHASECONFIG = 0x34; /* Gain = 3*2^13, source = EBUIN */ 965 PHASECONFIG = 0x34; /* Gain = 3*2^13, source = EBUIN */
1033#endif 966#endif
1034 pcmrec_dma_start(); 967 pcmrec_dma_start();
1035 968
@@ -1038,23 +971,16 @@ static void pcmrec_init(void)
1038 971
1039static void pcmrec_close(void) 972static void pcmrec_close(void)
1040{ 973{
1041#ifdef HAVE_UDA1380
1042 uda1380_disable_recording();
1043#endif
1044#ifdef HAVE_TLV320
1045 tlv320_disable_recording();
1046#endif
1047
1048#ifdef HAVE_SPDIF_POWER
1049 spdif_power_enable(spdif_power_setting);
1050#endif
1051 DMAROUTE = (DMAROUTE & 0xffff00ff); 974 DMAROUTE = (DMAROUTE & 0xffff00ff);
1052 ICR7 = 0x00; /* Disable interrupt */ 975 ICR7 = 0x00; /* Disable interrupt */
1053 IMR |= (1<<15); /* bit 15 is DMA1 */ 976 IMR |= (1<<15); /* bit 15 is DMA1 */
1054 977
978 pcmrec_dma_stop();
979
1055 /* Reset PDIR2 data flow */ 980 /* Reset PDIR2 data flow */
1056 DATAINCONTROL = 0x200; 981 DATAINCONTROL = 0x200;
1057 close_done = true; 982 close_done = true;
983 init_done = false;
1058} 984}
1059 985
1060static void pcmrec_thread(void) 986static void pcmrec_thread(void)
@@ -1064,10 +990,10 @@ static void pcmrec_thread(void)
1064 logf("thread pcmrec start"); 990 logf("thread pcmrec start");
1065 991
1066 error_count = 0; 992 error_count = 0;
1067 993
1068 while (1) 994 while(1)
1069 { 995 {
1070 queue_wait_w_tmo(&pcmrec_queue, &ev, HZ / 40); 996 queue_wait_w_tmo(&pcmrec_queue, &ev, HZ / 4);
1071 997
1072 switch (ev.id) 998 switch (ev.id)
1073 { 999 {
@@ -1104,8 +1030,9 @@ static void pcmrec_thread(void)
1104 break; 1030 break;
1105 1031
1106 case SYS_USB_CONNECTED: 1032 case SYS_USB_CONNECTED:
1107 if (!is_recording && !is_stopping) 1033 if (!is_recording)
1108 { 1034 {
1035 pcmrec_close();
1109 usb_acknowledge(SYS_USB_CONNECTED_ACK); 1036 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1110 usb_wait_for_disconnect(&pcmrec_queue); 1037 usb_wait_for_disconnect(&pcmrec_queue);
1111 } 1038 }
@@ -1148,3 +1075,102 @@ void pcm_rec_mux(int source)
1148 /* iAudio x5 */ 1075 /* iAudio x5 */
1149#endif 1076#endif
1150} 1077}
1078
1079
1080/****************************************************************************/
1081/* */
1082/* following functions will be called by the encoder codec */
1083/* */
1084/****************************************************************************/
1085
1086/* pass the encoder buffer pointer/size, mono/stereo, quality to the encoder */
1087void enc_get_inputs(int *buffer_size, int *channels, int *quality)
1088{
1089 *buffer_size = enc_buffer_size;
1090 *channels = enc_channels;
1091 *quality = enc_quality;
1092}
1093
1094/* set the encoder dimensions (called by encoder codec at initialization) */
1095void enc_set_parameters(int chunk_size, int num_chunks, int samp_per_chunk,
1096 char *head_ptr, int head_size, int enc_id)
1097{
1098 /* set read_pos just in front of current write_pos */
1099 read_pos = (write_pos - CHUNK_SIZE) & CHUNK_MASK;
1100
1101 enc_rd_index = 0; /* reset */
1102 enc_wr_index = 0; /* reset */
1103 enc_chunk_size = chunk_size; /* max chunk size */
1104 enc_num_chunks = num_chunks; /* total number of chunks */
1105 enc_samp_per_chunk = samp_per_chunk; /* pcm samples / encoderchunk */
1106 enc_head_buffer = head_ptr; /* optional file header data (wav) */
1107 enc_head_size = head_size; /* optional file header data (wav) */
1108 audio_enc_id = enc_id; /* AFMT_* id */
1109}
1110
1111/* allocate encoder chunk */
1112unsigned int *enc_alloc_chunk(void)
1113{
1114 return (unsigned int*)(enc_buffer + enc_wr_index * enc_chunk_size);
1115}
1116
1117/* free previously allocated encoder chunk */
1118void enc_free_chunk(void)
1119{
1120 unsigned long *enc_chunk;
1121
1122 enc_chunk = GET_ENC_CHUNK(enc_wr_index);
1123 curr_chunk_cnt++;
1124/* curr_bit_rate += *enc_chunk * 44100 * 8 / (enc_samp_per_chunk * 1000); */
1125 curr_bit_rate += *enc_chunk * 441 * 8 / (enc_samp_per_chunk * 10 );
1126 avrg_bit_rate = (curr_bit_rate + curr_chunk_cnt / 2) / curr_chunk_cnt;
1127
1128 /* advance enc_wr_index to the next chunk */
1129 enc_wr_index = (enc_wr_index + 1) % enc_num_chunks;
1130
1131 /* buffer full: advance enc_rd_index (for prerecording purpose) */
1132 if (enc_rd_index == enc_wr_index)
1133 {
1134 enc_rd_index = (enc_rd_index + 1) % enc_num_chunks;
1135 }
1136}
1137
1138/* checks near empty state on wav input buffer */
1139int enc_wavbuf_near_empty(void)
1140{
1141 /* less than 1sec raw data? => unboost encoder */
1142 if (((write_pos - read_pos) & CHUNK_MASK) < 44100*4)
1143 return 1;
1144 else
1145 return 0;
1146}
1147
1148/* passes a pointer to next chunk of unprocessed wav data */
1149char *enc_get_wav_data(int size)
1150{
1151 char *ptr;
1152 int avail;
1153
1154 /* limit the requested pcm data size */
1155 if(size > MAX_FEED_SIZE)
1156 size = MAX_FEED_SIZE;
1157
1158 avail = (write_pos - read_pos) & CHUNK_MASK;
1159
1160 if (avail >= size)
1161 {
1162 ptr = rec_buffer + read_pos;
1163 read_pos = (read_pos + size) & CHUNK_MASK;
1164
1165 /* ptr must point to continous data at wraparound position */
1166 if (read_pos < size)
1167 memcpy(rec_buffer + NUM_CHUNKS * CHUNK_SIZE,
1168 rec_buffer, read_pos);
1169
1170 wav_queue_empty = false;
1171 return ptr;
1172 }
1173
1174 wav_queue_empty = true;
1175 return NULL;
1176}