]> git.sesse.net Git - mlt/blobdiff - src/modules/core/filter_audioconvert.c
Fix reading binary files on Windows.
[mlt] / src / modules / core / filter_audioconvert.c
index 065dc75ae15dbece698a10f7d45d3dba01021d46..ad1e943375d5c0dd2c91089ee34d9ba892bbf28e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * filter_audioconvert.c -- convert from one audio format to another
- * Copyright (C) 2009 Ushodaya Enterprises Limited
+ * Copyright (C) 2009-2012 Ushodaya Enterprises Limited
  * Author: Dan Dennedy <dan@dennedy.org>
  *
  * This library is free software; you can redistribute it and/or
 #include <stdio.h>
 #include <stdlib.h>
 
+#ifndef CLAMP
+#define CLAMP( x, min, max ) (x) < (min) ? (min) : (x) > (max) ? (max) : (x)
+#endif
+
 static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *format, mlt_audio_format requested_format )
 {
-       int error = 0;
+       int error = 1;
        mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
        int channels = mlt_properties_get_int( properties, "audio_channels" );
        int samples = mlt_properties_get_int( properties, "audio_samples" );
-       int size = 0;
+       int size = mlt_audio_format_size( requested_format, samples, channels );
 
        if ( *format != requested_format )
        {
@@ -45,7 +49,6 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                        {
                        case mlt_audio_s32:
                        {
-                               size = channels * samples * sizeof(int32_t);
                                int32_t *buffer = mlt_pool_alloc( size );
                                int32_t *p = buffer;
                                int c;
@@ -60,11 +63,11 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                        }
                                }
                                *audio = buffer;
+                               error = 0;
                                break;
                        }
                        case mlt_audio_float:
                        {
-                               size = channels * samples * sizeof(float);
                                float *buffer = mlt_pool_alloc( size );
                                float *p = buffer;
                                int c;
@@ -79,10 +82,50 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                        }
                                }
                                *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = (int32_t) *q++ << 16;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = (float)( *q++ ) / 32768.0;
+                                       *p++ = CLAMP( f, -1.0f, 1.0f );
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               int16_t *q = (int16_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( *q++ >> 8 ) + 128;
+                               *audio = buffer;
+                               error = 0;
                                break;
                        }
                        default:
-                               error = 1;
+                               break;
                        }
                        break;
                case mlt_audio_s32:
@@ -90,7 +133,6 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                        {
                        case mlt_audio_s16:
                        {
-                               size = channels * samples * sizeof(int16_t);
                                int16_t *buffer = mlt_pool_alloc( size );
                                int16_t *p = buffer;
                                int32_t *q = (int32_t*) *audio;
@@ -99,11 +141,11 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                        for ( c = 0; c < channels; c++ )
                                                *p++ = *( q + c * samples + s ) >> 16;
                                *audio = buffer;
+                               error = 0;
                                break;
                        }
                        case mlt_audio_float:
                        {
-                               size = channels * samples * sizeof(float);
                                float *buffer = mlt_pool_alloc( size );
                                float *p = buffer;
                                int32_t *q = (int32_t*) *audio;
@@ -111,10 +153,53 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                while ( --i )
                                        *p++ = (float)( *q++ ) / 2147483648.0;
                                *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = *( q + c * samples + s );
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = (float)( *( q + c * samples + s ) ) / 2147483648.0;
+                                               *p++ = CLAMP( f, -1.0f, 1.0f );
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = ( q[c * samples + s] >> 24 ) + 128;
+                               *audio = buffer;
+                               error = 0;
                                break;
                        }
                        default:
-                               error = 1;
+                               break;
                        }
                        break;
                case mlt_audio_float:
@@ -122,7 +207,6 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                        {
                        case mlt_audio_s16:
                        {
-                               size = channels * samples * sizeof(int16_t);
                                int16_t *buffer = mlt_pool_alloc( size );
                                int16_t *p = buffer;
                                float *q = (float*) *audio;
@@ -131,37 +215,349 @@ static int convert_audio( mlt_frame frame, void **audio, mlt_audio_format *forma
                                        for ( c = 0; c < channels; c++ )
                                        {
                                                float f = *( q + c * samples + s );
-                                               f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
+                                               f = CLAMP( f, -1.0f, 1.0f );
                                                *p++ = 32767 * f;
                                        }
                                *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = *q++;
+                                       f = CLAMP( f, -1.0f, 1.0f );
+                                       int64_t pcm = ( f > 0.0f ? 2147483647LL : 2147483648LL ) * f;
+                                       *p++ = CLAMP( pcm, -2147483648LL, 2147483647LL );
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = *( q + c * samples + s );
+                                               f = CLAMP( f, -1.0f, 1.0f );
+                                               int64_t pcm = ( f > 0.0f ? 2147483647LL : 2147483648LL ) * f;
+                                               *p++ = CLAMP( pcm, -2147483648LL, 2147483647LL );
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                               *p++ = *( q + c * samples + s );
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int s, c;
+                               for ( s = 0; s < samples; s++ )
+                                       for ( c = 0; c < channels; c++ )
+                                       {
+                                               float f = *( q + c * samples + s );
+                                               f = CLAMP( f, -1.0f, 1.0f );
+                                               *p++ = ( 127 * f ) + 128;
+                                       }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       default:
+                               break;
+                       }
+                       break;
+               case mlt_audio_s32le:
+                       switch ( requested_format )
+                       {
+                       case mlt_audio_s16:
+                       {
+                               int16_t *buffer = mlt_pool_alloc( size );
+                               int16_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = *q++ >> 16;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       int32_t *q = (int32_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = *q;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_float:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       int32_t *q = (int32_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = (float)( *q ) / 2147483648.0;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = (float)( *q++ ) / 2147483648.0;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
+                               int32_t *q = (int32_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( *q++ >> 24 ) + 128;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       default:
+                               break;
+                       }
+                       break;
+               case mlt_audio_f32le:
+                       switch ( requested_format )
+                       {
+                       case mlt_audio_s16:
+                       {
+                               int16_t *buffer = mlt_pool_alloc( size );
+                               int16_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = *q++;
+                                       f = CLAMP( f, -1.0f , 1.0f );
+                                       *p++ = 32767 * f;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_float:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       float *q = (float*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = *q;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               error = 0;
                                break;
                        }
                        case mlt_audio_s32:
                        {
-                               size = channels * samples * sizeof(int32_t);
                                int32_t *buffer = mlt_pool_alloc( size );
                                int32_t *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       float *q = (float*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               float f = *q;
+                                               f = CLAMP( f, -1.0f , 1.0f );
+                                               int64_t pcm = ( f > 0.0f ? 2147483647LL : 2147483648LL ) * f;
+                                               *p++ = CLAMP( pcm, -2147483648LL, 2147483647LL );
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               float *q = (float*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = *q++;
+                                       f = CLAMP( f, -1.0f , 1.0f );
+                                       int64_t pcm = ( f > 0.0f ? 2147483647LL : 2147483648LL ) * f;
+                                       *p++ = CLAMP( pcm, -2147483648LL, 2147483647LL );
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_u8:
+                       {
+                               uint8_t *buffer = mlt_pool_alloc( size );
+                               uint8_t *p = buffer;
                                float *q = (float*) *audio;
                                int i = samples * channels + 1;
                                while ( --i )
                                {
                                        float f = *q++;
-                                       f = f > 1.0 ? 1.0 : f < -1.0 ? -1.0 : f;
-                                       *p++ = ( f > 0 ? 2147483647LL : 2147483648LL ) * f;
+                                       f = CLAMP( f, -1.0f , 1.0f );
+                                       *p++ = ( 127 * f ) + 128;
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       default:
+                               break;
+                       }
+                       break;
+               case mlt_audio_u8:
+                       switch ( requested_format )
+                       {
+                       case mlt_audio_s32:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       uint8_t *q = (uint8_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = ( (int32_t) *q - 128 ) << 24;
+                                               q += channels;
+                                       }
+                               }
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_float:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               int c;
+                               for ( c = 0; c < channels; c++ )
+                               {
+                                       uint8_t *q = (uint8_t*) *audio + c;
+                                       int i = samples + 1;
+                                       while ( --i )
+                                       {
+                                               *p++ = ( (float) *q - 128 ) / 256.0f;
+                                               q += channels;
+                                       }
                                }
                                *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s16:
+                       {
+                               int16_t *buffer = mlt_pool_alloc( size );
+                               int16_t *p = buffer;
+                               uint8_t *q = (uint8_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( (int16_t) *q++ - 128 ) << 8;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_s32le:
+                       {
+                               int32_t *buffer = mlt_pool_alloc( size );
+                               int32_t *p = buffer;
+                               uint8_t *q = (uint8_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                                       *p++ = ( (int32_t) *q++ - 128 ) << 24;
+                               *audio = buffer;
+                               error = 0;
+                               break;
+                       }
+                       case mlt_audio_f32le:
+                       {
+                               float *buffer = mlt_pool_alloc( size );
+                               float *p = buffer;
+                               uint8_t *q = (uint8_t*) *audio;
+                               int i = samples * channels + 1;
+                               while ( --i )
+                               {
+                                       float f = ( (float) *q++ - 128 ) / 256.0f;
+                                       *p++ = CLAMP( f, -1.0f, 1.0f );
+                               }
+                               *audio = buffer;
+                               error = 0;
                                break;
                        }
                        default:
-                               error = 1;
+                               break;
                        }
                        break;
                default:
-                       error = 1;
+                       break;
                }
        }
-       if ( size )
+       if ( !error )
        {
                mlt_frame_set_audio( frame, *audio, requested_format, size, mlt_pool_release );
                *format = requested_format;
@@ -183,7 +579,7 @@ static mlt_frame filter_process( mlt_filter this, mlt_frame frame )
 
 mlt_filter filter_audioconvert_init( mlt_profile profile, mlt_service_type type, const char *id, char *arg )
 {
-       mlt_filter this = calloc( sizeof( struct mlt_filter_s ), 1 );
+       mlt_filter this = calloc( 1, sizeof( struct mlt_filter_s ) );
        if ( mlt_filter_init( this, this ) == 0 )
                this->process = filter_process;
        return this;