1 /*
2 * filter_mono.c -- mix all channels to a mono signal across n channels
3 * Copyright (C) 2003-2018 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 <stdio.h>
25 #include <stdlib.h>
26
27 /** Get the audio.
28 */
29
filter_get_audio(mlt_frame frame,void ** buffer,mlt_audio_format * format,int * frequency,int * channels,int * samples)30 static int filter_get_audio( mlt_frame frame, void **buffer, mlt_audio_format *format, int *frequency, int *channels, int *samples )
31 {
32 // Get the properties of the a frame
33 mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
34 int channels_out = mlt_properties_get_int( properties, "mono.channels" );
35 int i, j, size;
36
37 // Get the producer's audio
38 mlt_frame_get_audio( frame, buffer, format, frequency, channels, samples );
39
40 if ( channels_out == -1 )
41 channels_out = *channels;
42 size = mlt_audio_format_size( *format, *samples, channels_out );
43
44 switch ( *format )
45 {
46 case mlt_audio_u8:
47 {
48 uint8_t *new_buffer = mlt_pool_alloc( size );
49 for ( i = 0; i < *samples; i++ )
50 {
51 uint8_t mixdown = 0;
52 for ( j = 0; j < *channels; j++ )
53 mixdown += ((uint8_t*) *buffer)[ ( i * *channels ) + j ];
54 for ( j = 0; j < channels_out; j++ )
55 new_buffer[ ( i * channels_out ) + j ] = mixdown;
56 }
57 *buffer = new_buffer;
58 break;
59 }
60 case mlt_audio_s16:
61 {
62 int16_t *new_buffer = mlt_pool_alloc( size );
63 for ( i = 0; i < *samples; i++ )
64 {
65 int16_t mixdown = 0;
66 for ( j = 0; j < *channels; j++ )
67 mixdown += ((int16_t*) *buffer)[ ( i * *channels ) + j ];
68 for ( j = 0; j < channels_out; j++ )
69 new_buffer[ ( i * channels_out ) + j ] = mixdown;
70 }
71 *buffer = new_buffer;
72 break;
73 }
74 case mlt_audio_s32le:
75 {
76 int32_t *new_buffer = mlt_pool_alloc( size );
77 for ( i = 0; i < *samples; i++ )
78 {
79 int32_t mixdown = 0;
80 for ( j = 0; j < *channels; j++ )
81 mixdown += ((int32_t*) *buffer)[ ( i * *channels ) + j ];
82 for ( j = 0; j < channels_out; j++ )
83 new_buffer[ ( i * channels_out ) + j ] = mixdown;
84 }
85 *buffer = new_buffer;
86 break;
87 }
88 case mlt_audio_f32le:
89 {
90 float *new_buffer = mlt_pool_alloc( size );
91 for ( i = 0; i < *samples; i++ )
92 {
93 float mixdown = 0;
94 for ( j = 0; j < *channels; j++ )
95 mixdown += ((float*) *buffer)[ ( i * *channels ) + j ];
96 for ( j = 0; j < channels_out; j++ )
97 new_buffer[ ( i * channels_out ) + j ] = mixdown;
98 }
99 *buffer = new_buffer;
100 break;
101 }
102 case mlt_audio_s32:
103 {
104 int32_t *new_buffer = mlt_pool_alloc( size );
105 for ( i = 0; i < *samples; i++ )
106 {
107 int32_t mixdown = 0;
108 for ( j = 0; j < *channels; j++ )
109 mixdown += ((int32_t*) *buffer)[ ( j * *channels ) + i ];
110 for ( j = 0; j < channels_out; j++ )
111 new_buffer[ ( j * *samples ) + i ] = mixdown;
112 }
113 *buffer = new_buffer;
114 break;
115 }
116 case mlt_audio_float:
117 {
118 float *new_buffer = mlt_pool_alloc( size );
119 for ( i = 0; i < *samples; i++ )
120 {
121 float mixdown = 0;
122 for ( j = 0; j < *channels; j++ )
123 mixdown += ((float*) *buffer)[ ( j * *channels ) + i ];
124 for ( j = 0; j < channels_out; j++ )
125 new_buffer[ ( j * *samples ) + i ] = mixdown;
126 }
127 *buffer = new_buffer;
128 break;
129 }
130 default:
131 mlt_log_error( NULL, "[filter mono] Invalid audio format\n" );
132 break;
133 }
134 if ( size > *samples * channels_out )
135 {
136 mlt_frame_set_audio( frame, *buffer, *format, size, mlt_pool_release );
137 *channels = channels_out;
138 }
139
140 return 0;
141 }
142
143 /** Filter processing.
144 */
145
filter_process(mlt_filter filter,mlt_frame frame)146 static mlt_frame filter_process( mlt_filter filter, mlt_frame frame )
147 {
148 mlt_properties properties = MLT_FILTER_PROPERTIES( filter );
149 mlt_properties frame_props = MLT_FRAME_PROPERTIES( frame );
150
151 // Propagate the parameters
152 mlt_properties_set_int( frame_props, "mono.channels", mlt_properties_get_int( properties, "channels" ) );
153
154 // Override the get_audio method
155 mlt_frame_push_audio( frame, filter_get_audio );
156
157 return frame;
158 }
159
160 /** Constructor for the filter.
161 */
162
filter_mono_init(mlt_profile profile,mlt_service_type type,const char * id,char * arg)163 mlt_filter filter_mono_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
164 {
165 mlt_filter filter = mlt_filter_new( );
166 if ( filter != NULL )
167 {
168 filter->process = filter_process;
169 if ( arg != NULL )
170 mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "channels", atoi( arg ) );
171 else
172 mlt_properties_set_int( MLT_FILTER_PROPERTIES( filter ), "channels", -1 );
173 }
174 return filter;
175 }
176
177