summaryrefslogtreecommitdiff
path: root/apps/codecs/wavpack_enc.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2006-08-28 22:38:41 +0000
committerMichael Sevakis <jethead71@rockbox.org>2006-08-28 22:38:41 +0000
commit4fc717a4c19a1fe0349977d7b9c86561c5a5cf2d (patch)
treeeb6113c7491072f7b5136e24775737764e2cdede /apps/codecs/wavpack_enc.c
parent65c2c58b3aa26164bd919665e4d710efa2fa7c79 (diff)
downloadrockbox-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/wavpack_enc.c')
-rw-r--r--apps/codecs/wavpack_enc.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/apps/codecs/wavpack_enc.c b/apps/codecs/wavpack_enc.c
new file mode 100644
index 0000000..cde2087
--- /dev/null
+++ b/apps/codecs/wavpack_enc.c
@@ -0,0 +1,230 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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"
+#include "libwavpack/wavpack.h"
+
+CODEC_HEADER
+
+typedef unsigned long uint32;
+typedef unsigned short uint16;
+typedef unsigned char uint8;
+
+static unsigned char wav_header_ster [46] =
+{33,22,'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 [46] =
+{33,22,'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};
+
+static struct codec_api *ci;
+static int enc_channels;
+
+#define CHUNK_SIZE 20000
+
+static long input_buffer[CHUNK_SIZE/2] IBSS_ATTR;
+
+void *memset(void *s, int c, size_t n)
+{
+ return(ci->memset(s,c,n));
+}
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+ return(ci->memcpy(dest,src,n));
+}
+
+/* update file header info callback function */
+void enc_set_header(void *head_buffer, /* ptr to the file header data */
+ int head_size, /* size of this header data */
+ int num_pcm_sampl, /* amount of processed pcm samples */
+ bool is_file_header) /* update file/chunk header */
+{
+ if(is_file_header)
+ {
+ /* update file header before file closing */
+ if(sizeof(WavpackHeader) + sizeof(wav_header_mono) < (unsigned)head_size)
+ {
+ char* riff_header = (char*)head_buffer + sizeof(WavpackHeader);
+ char* wv_header = (char*)head_buffer + sizeof(wav_header_mono);
+ int num_file_bytes = num_pcm_sampl * 2 * enc_channels;
+ unsigned long ckSize;
+
+ /* RIFF header and WVPK header have to be swapped */
+ /* copy wavpack header to file start position */
+ ci->memcpy(head_buffer, wv_header, sizeof(WavpackHeader));
+ wv_header = head_buffer; /* recalc wavpack header position */
+
+ if(enc_channels == 2)
+ ci->memcpy(riff_header, wav_header_ster, sizeof(wav_header_ster));
+ else
+ ci->memcpy(riff_header, wav_header_mono, sizeof(wav_header_mono));
+
+ /* update the Wavpack header first chunk size & total frame count */
+ ckSize = htole32(((WavpackHeader*)wv_header)->ckSize)
+ + sizeof(wav_header_mono);
+ ((WavpackHeader*)wv_header)->total_samples = htole32(num_pcm_sampl);
+ ((WavpackHeader*)wv_header)->ckSize = htole32(ckSize);
+
+ /* update the RIFF WAV header size entries */
+ *(long*)(riff_header+ 6) = htole32(num_file_bytes + 36);
+ *(long*)(riff_header+42) = htole32(num_file_bytes);
+ }
+ }
+ else
+ {
+ /* update timestamp (block_index) */
+ ((WavpackHeader*)head_buffer)->block_index = htole32(num_pcm_sampl);
+ }
+}
+
+
+enum codec_status codec_start(struct codec_api* api)
+{
+ int i;
+ long t;
+ uint32 *src;
+ uint32 *dst;
+ int chunk_size, num_chunks, samp_per_chunk;
+ int enc_buffer_size;
+ int enc_quality;
+ WavpackConfig config;
+ WavpackContext *wpc;
+ 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 */
+ /* add wav_header_mono as place holder to file start position */
+ /* wav header and wvpk header have to be reordered later */
+ ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
+ wav_header_mono, sizeof(wav_header_mono),
+ AFMT_WAVPACK);
+
+ wpc = WavpackOpenFileOutput ();
+
+ memset (&config, 0, sizeof (config));
+ config.bits_per_sample = 16;
+ config.bytes_per_sample = 2;
+ config.sample_rate = 44100;
+ config.num_channels = enc_channels;
+
+ if (!WavpackSetConfiguration (wpc, &config, 1))
+ return CODEC_ERROR;
+
+ /* main application waits for this flag during encoder loading */
+ ci->enc_codec_loaded = true;
+
+ /* main encoding loop */
+ while(!ci->stop_codec)
+ {
+ while((src = (uint32*)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 = (uint32*)ci->enc_alloc_chunk() + 1;
+
+ WavpackStartBlock (wpc, (uint8*)dst, (uint8*)dst + CHUNK_SIZE);
+
+ if(enc_channels == 2)
+ {
+ for (i=0; i<CHUNK_SIZE/4; i++)
+ {
+ t = (long)*src++;
+
+ input_buffer[2*i + 0] = t >> 16;
+ input_buffer[2*i + 1] = (short)t;
+ }
+ }
+ else
+ {
+ for (i=0; i<CHUNK_SIZE/4; i++)
+ {
+ t = (long)*src++;
+ t = (((t<<16)>>16) + (t>>16)) >> 1; /* left+right */
+
+ input_buffer[i] = t;
+ }
+ }
+
+ if (!WavpackPackSamples (wpc, input_buffer, CHUNK_SIZE/4))
+ return CODEC_ERROR;
+
+ /* finish the chunk and store chunk size info */
+ dst[-1] = WavpackFinishBlock (wpc);
+
+ 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