summaryrefslogtreecommitdiff
path: root/apps/codecs/wavpack_enc.c
diff options
context:
space:
mode:
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 0000000000..cde208739f
--- /dev/null
+++ b/apps/codecs/wavpack_enc.c
@@ -0,0 +1,230 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Antonius Hellmann
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef SIMULATOR
21
22#include "codeclib.h"
23#include "libwavpack/wavpack.h"
24
25CODEC_HEADER
26
27typedef unsigned long uint32;
28typedef unsigned short uint16;
29typedef unsigned char uint8;
30
31static unsigned char wav_header_ster [46] =
32{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
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};
34
35static unsigned char wav_header_mono [46] =
36{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
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};
38
39static struct codec_api *ci;
40static int enc_channels;
41
42#define CHUNK_SIZE 20000
43
44static long input_buffer[CHUNK_SIZE/2] IBSS_ATTR;
45
46void *memset(void *s, int c, size_t n)
47{
48 return(ci->memset(s,c,n));
49}
50
51void *memcpy(void *dest, const void *src, size_t n)
52{
53 return(ci->memcpy(dest,src,n));
54}
55
56/* update file header info callback function */
57void enc_set_header(void *head_buffer, /* ptr to the file header data */
58 int head_size, /* size of this header data */
59 int num_pcm_sampl, /* amount of processed pcm samples */
60 bool is_file_header) /* update file/chunk header */
61{
62 if(is_file_header)
63 {
64 /* update file header before file closing */
65 if(sizeof(WavpackHeader) + sizeof(wav_header_mono) < (unsigned)head_size)
66 {
67 char* riff_header = (char*)head_buffer + sizeof(WavpackHeader);
68 char* wv_header = (char*)head_buffer + sizeof(wav_header_mono);
69 int num_file_bytes = num_pcm_sampl * 2 * enc_channels;
70 unsigned long ckSize;
71
72 /* RIFF header and WVPK header have to be swapped */
73 /* copy wavpack header to file start position */
74 ci->memcpy(head_buffer, wv_header, sizeof(WavpackHeader));
75 wv_header = head_buffer; /* recalc wavpack header position */
76
77 if(enc_channels == 2)
78 ci->memcpy(riff_header, wav_header_ster, sizeof(wav_header_ster));
79 else
80 ci->memcpy(riff_header, wav_header_mono, sizeof(wav_header_mono));
81
82 /* update the Wavpack header first chunk size & total frame count */
83 ckSize = htole32(((WavpackHeader*)wv_header)->ckSize)
84 + sizeof(wav_header_mono);
85 ((WavpackHeader*)wv_header)->total_samples = htole32(num_pcm_sampl);
86 ((WavpackHeader*)wv_header)->ckSize = htole32(ckSize);
87
88 /* update the RIFF WAV header size entries */
89 *(long*)(riff_header+ 6) = htole32(num_file_bytes + 36);
90 *(long*)(riff_header+42) = htole32(num_file_bytes);
91 }
92 }
93 else
94 {
95 /* update timestamp (block_index) */
96 ((WavpackHeader*)head_buffer)->block_index = htole32(num_pcm_sampl);
97 }
98}
99
100
101enum codec_status codec_start(struct codec_api* api)
102{
103 int i;
104 long t;
105 uint32 *src;
106 uint32 *dst;
107 int chunk_size, num_chunks, samp_per_chunk;
108 int enc_buffer_size;
109 int enc_quality;
110 WavpackConfig config;
111 WavpackContext *wpc;
112 bool cpu_boosted = true; /* start boosted */
113
114 ci = api; // copy to global api pointer
115
116 if(ci->enc_get_inputs == NULL ||
117 ci->enc_set_parameters == NULL ||
118 ci->enc_alloc_chunk == NULL ||
119 ci->enc_free_chunk == NULL ||
120 ci->enc_wavbuf_near_empty == NULL ||
121 ci->enc_get_wav_data == NULL ||
122 ci->enc_set_header_callback == NULL )
123 return CODEC_ERROR;
124
125 ci->cpu_boost(true);
126
127 *ci->enc_set_header_callback = enc_set_header;
128 ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
129
130 /* configure the buffer system */
131 chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
132 num_chunks = enc_buffer_size / chunk_size;
133 samp_per_chunk = CHUNK_SIZE / 4;
134
135 /* inform the main program about buffer dimensions and other params */
136 /* add wav_header_mono as place holder to file start position */
137 /* wav header and wvpk header have to be reordered later */
138 ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
139 wav_header_mono, sizeof(wav_header_mono),
140 AFMT_WAVPACK);
141
142 wpc = WavpackOpenFileOutput ();
143
144 memset (&config, 0, sizeof (config));
145 config.bits_per_sample = 16;
146 config.bytes_per_sample = 2;
147 config.sample_rate = 44100;
148 config.num_channels = enc_channels;
149
150 if (!WavpackSetConfiguration (wpc, &config, 1))
151 return CODEC_ERROR;
152
153 /* main application waits for this flag during encoder loading */
154 ci->enc_codec_loaded = true;
155
156 /* main encoding loop */
157 while(!ci->stop_codec)
158 {
159 while((src = (uint32*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
160 {
161 if(ci->stop_codec)
162 break;
163
164 if(ci->enc_wavbuf_near_empty() == 0)
165 {
166 if(!cpu_boosted)
167 {
168 ci->cpu_boost(true);
169 cpu_boosted = true;
170 }
171 }
172
173 dst = (uint32*)ci->enc_alloc_chunk() + 1;
174
175 WavpackStartBlock (wpc, (uint8*)dst, (uint8*)dst + CHUNK_SIZE);
176
177 if(enc_channels == 2)
178 {
179 for (i=0; i<CHUNK_SIZE/4; i++)
180 {
181 t = (long)*src++;
182
183 input_buffer[2*i + 0] = t >> 16;
184 input_buffer[2*i + 1] = (short)t;
185 }
186 }
187 else
188 {
189 for (i=0; i<CHUNK_SIZE/4; i++)
190 {
191 t = (long)*src++;
192 t = (((t<<16)>>16) + (t>>16)) >> 1; /* left+right */
193
194 input_buffer[i] = t;
195 }
196 }
197
198 if (!WavpackPackSamples (wpc, input_buffer, CHUNK_SIZE/4))
199 return CODEC_ERROR;
200
201 /* finish the chunk and store chunk size info */
202 dst[-1] = WavpackFinishBlock (wpc);
203
204 ci->enc_free_chunk();
205 ci->yield();
206 }
207
208 if(ci->enc_wavbuf_near_empty())
209 {
210 if(cpu_boosted)
211 {
212 ci->cpu_boost(false);
213 cpu_boosted = false;
214 }
215 }
216 ci->yield();
217 }
218
219 if(cpu_boosted) /* set initial boost state */
220 ci->cpu_boost(false);
221
222 /* reset parameters to initial state */
223 ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
224
225 /* main application waits for this flag during encoder removing */
226 ci->enc_codec_loaded = false;
227
228 return CODEC_OK;
229}
230#endif