diff options
| author | Michael Sevakis <jethead71@rockbox.org> | 2006-08-28 22:38:41 +0000 |
|---|---|---|
| committer | Michael Sevakis <jethead71@rockbox.org> | 2006-08-28 22:38:41 +0000 |
| commit | 4fc717a4c19a1fe0349977d7b9c86561c5a5cf2d (patch) | |
| tree | eb6113c7491072f7b5136e24775737764e2cdede /apps/codecs/wav_enc.c | |
| parent | 65c2c58b3aa26164bd919665e4d710efa2fa7c79 (diff) | |
| download | rockbox-4fc717a4c19a1fe0349977d7b9c86561c5a5cf2d.zip rockbox-4fc717a4c19a1fe0349977d7b9c86561c5a5cf2d.tar.gz rockbox-4fc717a4c19a1fe0349977d7b9c86561c5a5cf2d.tar.bz2 rockbox-4fc717a4c19a1fe0349977d7b9c86561c5a5cf2d.tar.xz | |
Added FS#2939 Encoder Codec Interface + Codecs by Antonius Hellmann with additional FM Recording support and my modifications
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10789 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/wav_enc.c')
| -rw-r--r-- | apps/codecs/wav_enc.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c new file mode 100644 index 0000000..5aabb5d --- /dev/null +++ b/apps/codecs/wav_enc.c @@ -0,0 +1,172 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006 Antonius Hellmann + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef SIMULATOR + +#include "codeclib.h" + +CODEC_HEADER + +static struct codec_api *ci; +static int enc_channels; + +#define CHUNK_SIZE 8192 + +static unsigned char wav_header[44] = +{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16, + 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}; + +static unsigned char wav_header_mono[44] = +{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16, + 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}; + +/* update file header info callback function (called by main application) */ +void enc_set_header(void *head_buffer, /* ptr to the file header data */ + int head_size, /* size of this header data */ + int num_pcm_samples, /* amount of processed pcm samples */ + bool is_file_header) +{ + int num_file_bytes = num_pcm_samples * 2 * enc_channels; + + if(is_file_header) + { + /* update file header before file closing */ + if((int)sizeof(wav_header) < head_size) + { + /* update wave header size entries: special to WAV format */ + *(long*)(head_buffer+ 4) = htole32(num_file_bytes + 36); + *(long*)(head_buffer+40) = htole32(num_file_bytes); + } + } +} + +/* main codec entry point */ +enum codec_status codec_start(struct codec_api* api) +{ + int i; + long lr; + unsigned long t; + unsigned long *src; + unsigned long *dst; + int chunk_size, num_chunks, samp_per_chunk; + int enc_buffer_size; + int enc_quality; + bool cpu_boosted = true; /* start boosted */ + + ci = api; // copy to global api pointer + + if(ci->enc_get_inputs == NULL || + ci->enc_set_parameters == NULL || + ci->enc_alloc_chunk == NULL || + ci->enc_free_chunk == NULL || + ci->enc_wavbuf_near_empty == NULL || + ci->enc_get_wav_data == NULL || + ci->enc_set_header_callback == NULL ) + return CODEC_ERROR; + + ci->cpu_boost(true); + + *ci->enc_set_header_callback = enc_set_header; + ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality); + + /* configure the buffer system */ + chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2; + num_chunks = enc_buffer_size / chunk_size; + samp_per_chunk = CHUNK_SIZE / 4; + + /* inform the main program about buffer dimensions and other params */ + ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk, + (enc_channels == 2) ? wav_header : wav_header_mono, + sizeof(wav_header), AFMT_PCM_WAV); + + /* main application waits for this flag during encoder loading */ + ci->enc_codec_loaded = true; + + /* main encoding loop */ + while(!ci->stop_codec) + { + while((src = (unsigned long*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL) + { + if(ci->stop_codec) + break; + + if(ci->enc_wavbuf_near_empty() == 0) + { + if(!cpu_boosted) + { + ci->cpu_boost(true); + cpu_boosted = true; + } + } + + dst = (unsigned long*)ci->enc_alloc_chunk(); + *dst++ = CHUNK_SIZE * enc_channels / 2; /* set size info */ + + if(enc_channels == 2) + { + /* swap byte order & copy to destination */ + for (i=0; i<CHUNK_SIZE/4; i++) + { + t = *src++; + *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00); + } + } + else + { + /* mix left/right, swap byte order & copy to destination */ + for (i=0; i<CHUNK_SIZE/8; i++) + { + lr = (long)*src++; + lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */ + t = (lr << 16); + lr = (long)*src++; + lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */ + t |= lr & 0xffff; + *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00); + } + } + + ci->enc_free_chunk(); + ci->yield(); + } + + if(ci->enc_wavbuf_near_empty()) + { + if(cpu_boosted) + { + ci->cpu_boost(false); + cpu_boosted = false; + } + } + + ci->yield(); + } + + if(cpu_boosted) /* set initial boost state */ + ci->cpu_boost(false); + + /* reset parameters to initial state */ + ci->enc_set_parameters(0, 0, 0, 0, 0, 0); + + /* main application waits for this flag during encoder removing */ + ci->enc_codec_loaded = false; + + return CODEC_OK; +} +#endif |