diff options
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 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 | |||
24 | CODEC_HEADER | ||
25 | |||
26 | static struct codec_api *ci; | ||
27 | static int enc_channels; | ||
28 | |||
29 | #define CHUNK_SIZE 8192 | ||
30 | |||
31 | static 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 | |||
35 | static 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) */ | ||
40 | void 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 */ | ||
60 | enum 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 | ||