summaryrefslogtreecommitdiff
path: root/apps/codecs/wav_enc.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs/wav_enc.c')
-rw-r--r--apps/codecs/wav_enc.c172
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 0000000000..5aabb5d8e8
--- /dev/null
+++ b/apps/codecs/wav_enc.c
@@ -0,0 +1,172 @@
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
24CODEC_HEADER
25
26static struct codec_api *ci;
27static int enc_channels;
28
29#define CHUNK_SIZE 8192
30
31static unsigned char wav_header[44] =
32{'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[44] =
36{'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
39/* update file header info callback function (called by main application) */
40void enc_set_header(void *head_buffer, /* ptr to the file header data */
41 int head_size, /* size of this header data */
42 int num_pcm_samples, /* amount of processed pcm samples */
43 bool is_file_header)
44{
45 int num_file_bytes = num_pcm_samples * 2 * enc_channels;
46
47 if(is_file_header)
48 {
49 /* update file header before file closing */
50 if((int)sizeof(wav_header) < head_size)
51 {
52 /* update wave header size entries: special to WAV format */
53 *(long*)(head_buffer+ 4) = htole32(num_file_bytes + 36);
54 *(long*)(head_buffer+40) = htole32(num_file_bytes);
55 }
56 }
57}
58
59/* main codec entry point */
60enum codec_status codec_start(struct codec_api* api)
61{
62 int i;
63 long lr;
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
72 ci = api; // copy to global api pointer
73
74 if(ci->enc_get_inputs == NULL ||
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
83 ci->cpu_boost(true);
84
85 *ci->enc_set_header_callback = enc_set_header;
86 ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
87
88 /* configure the buffer system */
89 chunk_size = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
90 num_chunks = enc_buffer_size / chunk_size;
91 samp_per_chunk = CHUNK_SIZE / 4;
92
93 /* inform the main program about buffer dimensions and other params */
94 ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
95 (enc_channels == 2) ? wav_header : wav_header_mono,
96 sizeof(wav_header), AFMT_PCM_WAV);
97
98 /* main application waits for this flag during encoder loading */
99 ci->enc_codec_loaded = true;
100
101 /* main encoding loop */
102 while(!ci->stop_codec)
103 {
104 while((src = (unsigned long*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
105 {
106 if(ci->stop_codec)
107 break;
108
109 if(ci->enc_wavbuf_near_empty() == 0)
110 {
111 if(!cpu_boosted)
112 {
113 ci->cpu_boost(true);
114 cpu_boosted = true;
115 }
116 }
117
118 dst = (unsigned long*)ci->enc_alloc_chunk();
119 *dst++ = CHUNK_SIZE * enc_channels / 2; /* set size info */
120
121 if(enc_channels == 2)
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
145 ci->enc_free_chunk();
146 ci->yield();
147 }
148
149 if(ci->enc_wavbuf_near_empty())
150 {
151 if(cpu_boosted)
152 {
153 ci->cpu_boost(false);
154 cpu_boosted = false;
155 }
156 }
157
158 ci->yield();
159 }
160
161 if(cpu_boosted) /* set initial boost state */
162 ci->cpu_boost(false);
163
164 /* reset parameters to initial state */
165 ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
166
167 /* main application waits for this flag during encoder removing */
168 ci->enc_codec_loaded = false;
169
170 return CODEC_OK;
171}
172#endif