1 /*
2 * filter_audiochannels.c -- convert from one audio format to another
3 * Copyright (C) 2009-2014 Meltytech, LLC
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <framework/mlt_filter.h>
21 #include <framework/mlt_frame.h>
22 #include <framework/mlt_log.h>
23
24 #include <string.h>
25
filter_get_audio(mlt_frame frame,void ** buffer,mlt_audio_format * format,int * frequency,int * channels,int * samples)26 static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
27 {
28 // Used to return number of channels in the source
29 int channels_avail = *channels;
30
31 // Get the producer's audio
32 int error = mlt_frame_get_audio( frame, buffer, format, frequency, &channels_avail, samples );
33 if ( error ) return error;
34
35 if ( channels_avail < *channels )
36 {
37 int size = mlt_audio_format_size( *format, *samples, *channels );
38 int16_t *new_buffer = mlt_pool_alloc( size );
39
40 // Duplicate the existing channels
41 if ( *format == mlt_audio_s16 )
42 {
43 int i, j, k = 0;
44 for ( i = 0; i < *samples; i++ )
45 {
46 for ( j = 0; j < *channels; j++ )
47 {
48 new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + k ];
49 k = ( k + 1 ) % channels_avail;
50 }
51 }
52 }
53 else if ( *format == mlt_audio_s32le || *format == mlt_audio_f32le )
54 {
55 int32_t *p = (int32_t*) new_buffer;
56 int i, j, k = 0;
57 for ( i = 0; i < *samples; i++ )
58 {
59 for ( j = 0; j < *channels; j++ )
60 {
61 p[ ( i * *channels ) + j ] = ((int32_t*)(*buffer))[ ( i * channels_avail ) + k ];
62 k = ( k + 1 ) % channels_avail;
63 }
64 }
65 }
66 else if ( *format == mlt_audio_u8 )
67 {
68 uint8_t *p = (uint8_t*) new_buffer;
69 int i, j, k = 0;
70 for ( i = 0; i < *samples; i++ )
71 {
72 for ( j = 0; j < *channels; j++ )
73 {
74 p[ ( i * *channels ) + j ] = ((uint8_t*)(*buffer))[ ( i * channels_avail ) + k ];
75 k = ( k + 1 ) % channels_avail;
76 }
77 }
78 }
79 else
80 {
81 // non-interleaved - s32 or float
82 int size_avail = mlt_audio_format_size( *format, *samples, channels_avail );
83 int32_t *p = (int32_t*) new_buffer;
84 int i = *channels / channels_avail;
85 while ( i-- )
86 {
87 memcpy( p, *buffer, size_avail );
88 p += size_avail / sizeof(*p);
89 }
90 i = *channels % channels_avail;
91 if ( i )
92 {
93 size_avail = mlt_audio_format_size( *format, *samples, i );
94 memcpy( p, *buffer, size_avail );
95 }
96 }
97 // Update the audio buffer now - destroys the old
98 mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
99 *buffer = new_buffer;
100 }
101 else if ( channels_avail == 6 && *channels == 2 )
102 {
103 // Downmix 5.1 audio to stereo.
104 // Mix levels taken from ATSC A/52 assuming maximum center and surround
105 // mix levels.
106 #define MIX(front, center, surr) (front + (0.707 * center) + (0.5 * surr))
107
108 // Convert to a supported format if necessary
109 mlt_audio_format new_format = *format;
110 switch( *format )
111 {
112 default:
113 // Unknown. Try to convert to float anyway.
114 mlt_log_error( NULL, "[audiochannels] Unknown format %d\n", *format );
115 case mlt_audio_float:
116 case mlt_audio_f32le:
117 new_format = mlt_audio_float;
118 break;
119 case mlt_audio_s32le:
120 case mlt_audio_s32:
121 new_format = mlt_audio_s32;
122 break;
123 case mlt_audio_s16:
124 case mlt_audio_u8:
125 new_format = mlt_audio_s16;
126 break;
127 case mlt_audio_none:
128 new_format = mlt_audio_none;
129 break;
130 }
131 if ( *format != new_format && frame->convert_audio )
132 frame->convert_audio( frame, buffer, format, new_format );
133
134 // Perform the downmix. Operate on the buffer in place to avoid realloc.
135 if ( *format == mlt_audio_s16 )
136 {
137 int16_t* in = *buffer;
138 int16_t* out = *buffer;
139 int i;
140 for ( i = 0; i < *samples; i++ )
141 {
142 float fl = in[0];
143 float fr = in[1];
144 float c = in[2];
145 // in[3] is LFE
146 float sl = in[4];
147 float sr = in[5];
148 *out++ = CLAMP( MIX(fl, c, sl), INT16_MIN, INT16_MAX ); // Left
149 *out++ = CLAMP( MIX(fr, c, sr), INT16_MIN, INT16_MAX ); // Right
150 in +=6;
151 }
152 }
153 else if ( *format == mlt_audio_s32 )
154 {
155 int32_t* flin = *buffer;
156 int32_t* frin = *buffer + (*samples * sizeof(float));
157 int32_t* cin = *buffer + (2 * *samples * sizeof(float));
158 int32_t* slin = *buffer + (4 * *samples * sizeof(float));
159 int32_t* srin = *buffer + (5 * *samples * sizeof(float));
160 int32_t* lout = *buffer;
161 int32_t* rout = *buffer + (*samples * sizeof(float));
162 int i;
163 for ( i = 0; i < *samples; i++ )
164 {
165 double fl = *flin++;
166 double fr = *frin++;
167 double c = *cin++;
168 double sl = *slin++;
169 double sr = *srin++;
170 *lout++ = CLAMP( MIX(fl, c, sl), INT32_MIN, INT32_MAX );
171 *rout++ = CLAMP( MIX(fr, c, sr), INT32_MIN, INT32_MAX );
172 }
173 }
174 else if ( *format == mlt_audio_float )
175 {
176 float* flin = *buffer;
177 float* frin = *buffer + (*samples * sizeof(float));
178 float* cin = *buffer + (2 * *samples * sizeof(float));
179 float* slin = *buffer + (4 * *samples * sizeof(float));
180 float* srin = *buffer + (5 * *samples * sizeof(float));
181 float* lout = *buffer;
182 float* rout = *buffer + (*samples * sizeof(float));
183 int i;
184 for ( i = 0; i < *samples; i++ )
185 {
186 float fl = *flin++;
187 float fr = *frin++;
188 float c = *cin++;
189 float sl = *slin++;
190 float sr = *srin++;
191 *lout++ = MIX(fl, c, sl);
192 *rout++ = MIX(fr, c, sr);
193 }
194 }
195 else
196 {
197 mlt_log_error( NULL, "[audiochannels] Unable to mix format %d\n", *format );
198 }
199 }
200 else if ( channels_avail > *channels )
201 {
202 int size = mlt_audio_format_size( *format, *samples, *channels );
203 int16_t *new_buffer = mlt_pool_alloc( size );
204 int i, j;
205
206 // Drop all but the first *channels
207 if ( *format == mlt_audio_s16 )
208 {
209 for ( i = 0; i < *samples; i++ )
210 for ( j = 0; j < *channels; j++ )
211 new_buffer[ ( i * *channels ) + j ] = ((int16_t*)(*buffer))[ ( i * channels_avail ) + j ];
212 }
213 else if ( *format == mlt_audio_s32le || *format == mlt_audio_f32le )
214 {
215 int32_t *p = (int32_t*) new_buffer;
216 for ( i = 0; i < *samples; i++ )
217 for ( j = 0; j < *channels; j++ )
218 p[ ( i * *channels ) + j ] = ((int32_t*)(*buffer))[ ( i * channels_avail ) + j ];
219 }
220 else if ( *format == mlt_audio_u8 )
221 {
222 uint8_t *p = (uint8_t*) new_buffer;
223 for ( i = 0; i < *samples; i++ )
224 for ( j = 0; j < *channels; j++ )
225 p[ ( i * *channels ) + j ] = ((uint8_t*)(*buffer))[ ( i * channels_avail ) + j ];
226 }
227 else
228 {
229 // non-interleaved - s32 or float
230 memcpy( new_buffer, *buffer, size );
231 }
232 // Update the audio buffer now - destroys the old
233 mlt_frame_set_audio( frame, new_buffer, *format, size, mlt_pool_release );
234 *buffer = new_buffer;
235 }
236 return error;
237 }
238
239 /** Filter processing.
240 */
241
filter_process(mlt_filter filter,mlt_frame frame)242 static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
243 {
244 mlt_frame_push_audio( frame, filter_get_audio );
245 return frame;
246 }
247
248 /** Constructor for the filter.
249 */
250
filter_audiochannels_init(mlt_profile profile,mlt_service_type type,const char * id,char * arg)251 mlt_filter filter_audiochannels_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
252 {
253 mlt_filter filter = mlt_filter_new();
254 if ( filter )
255 filter->process = filter_process;
256 return filter;
257 }
258