]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
first pass of stereo support
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 12 Jun 2014 17:06:33 +0000 (22:06 +0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 12 Jun 2014 17:06:33 +0000 (22:06 +0500)
20 files changed:
src/include/switch_core.h
src/include/switch_module_interfaces.h
src/include/switch_resample.h
src/mod/applications/mod_conference/mod_conference.c
src/mod/asr_tts/mod_cepstral/mod_cepstral.c
src/mod/codecs/mod_opus/mod_opus.c
src/mod/formats/mod_local_stream/mod_local_stream.c
src/mod/formats/mod_shell_stream/mod_shell_stream.c
src/mod/formats/mod_shout/mod_shout.c
src/mod/formats/mod_tone_stream/mod_tone_stream.c
src/mod/formats/mod_vlc/mod_vlc.c
src/mod/languages/mod_v8/src/fssession.cpp
src/switch_core_codec.c
src/switch_core_file.c
src/switch_core_io.c
src/switch_core_speech.c
src/switch_ivr_async.c
src/switch_ivr_play_say.c
src/switch_pcm.c
src/switch_resample.c

index e38a8ae003d36f52b70d5d000a94e7941a4a3972..1414d518a24f065682417e9ca4f1abb82b4dedb0 100644 (file)
@@ -1870,7 +1870,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(_In_ switch_speech_handl
                                                                                                                const char *module_name,
                                                                                                                const char *voice_name,
                                                                                                                _In_ unsigned int rate,
-                                                                                                               _In_ unsigned int interval, switch_speech_flag_t *flags, _In_opt_ switch_memory_pool_t *pool);
+                                                                                                               _In_ unsigned int interval, 
+                                                                                                               _In_ unsigned int channels,
+                                                                                                               switch_speech_flag_t *flags, _In_opt_ switch_memory_pool_t *pool);
 /*! 
   \brief Feed text to the TTS module
   \param sh the speech handle to feed
index 62fea0b3f7ce13cd3734d75fe0e0fbf59846be8e..aff702962b9c3309131472a9de47224967016962 100644 (file)
@@ -311,6 +311,7 @@ struct switch_file_handle {
        uint32_t native_rate;
        /*! the number of channels */
        uint32_t channels;
+       uint32_t real_channels;
        /*! integer representation of the format */
        unsigned int format;
        /*! integer representation of the sections */
@@ -435,7 +436,7 @@ struct switch_speech_interface {
        /*! the name of the interface */
        const char *interface_name;
        /*! function to open the speech interface */
-       switch_status_t (*speech_open) (switch_speech_handle_t *sh, const char *voice_name, int rate, switch_speech_flag_t *flags);
+       switch_status_t (*speech_open) (switch_speech_handle_t *sh, const char *voice_name, int rate, int channels, switch_speech_flag_t *flags);
        /*! function to close the speech interface */
        switch_status_t (*speech_close) (switch_speech_handle_t *, switch_speech_flag_t *flags);
        /*! function to feed audio to the ASR */
@@ -466,6 +467,8 @@ struct switch_speech_handle {
        uint32_t rate;
        uint32_t speed;
        uint32_t samples;
+       uint32_t channels;
+       uint32_t real_channels;
        char voice[80];
        char *engine;
        /*! module specific param */
@@ -599,6 +602,8 @@ struct switch_codec_fmtp {
        int bits_per_second;
        /*! number of microseconds of media in one packet (ptime * 1000) */
        int microseconds_per_packet;
+       /*! stereo  */
+       int stereo;
        /*! private data for the codec module to store handle specific info */
        void *private_info;
 
index bc1677079f82740b6c32064bc8f5f96ef3e6f1ec..355510f575f7357dc739078b24c56faac73bafc9 100644 (file)
@@ -67,6 +67,8 @@ SWITCH_BEGIN_EXTERN_C
        uint32_t to_len;
        /*! the total size of the to buffer */
        uint32_t to_size;
+       /*! the number of channels */
+       int channels;
 
 } switch_audio_resampler_t;
 
@@ -171,7 +173,7 @@ SWITCH_DECLARE(void) switch_change_sln_volume_granular(int16_t *data, uint32_t s
 
 SWITCH_DECLARE(uint32_t) switch_merge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples);
 SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int16_t *other_data, uint32_t other_samples);
-SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t channels);
+SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels);
 
 SWITCH_END_EXTERN_C
 #endif
index 36ecbf7d43c7bb3bf7070a3c77ef8c5c05f41362..f04581736d2250a35a4fb7df7902e9af5cf1134c 100644 (file)
@@ -359,6 +359,7 @@ typedef struct conference_obj {
        switch_mutex_t *flag_mutex;
        uint32_t rate;
        uint32_t interval;
+       uint32_t channels;
        switch_mutex_t *mutex;
        conference_member_t *members;
        conference_member_t *floor_holder;
@@ -2532,7 +2533,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
        conference_obj_t *conference = (conference_obj_t *) obj;
        conference_member_t *imember, *omember;
        uint32_t samples = switch_samples_per_packet(conference->rate, conference->interval);
-       uint32_t bytes = samples * 2;
+       uint32_t bytes = samples * 2 * conference->channels;
        uint8_t ready = 0, total = 0;
        switch_timer_t timer = { 0 };
        switch_event_t *event;
@@ -2595,12 +2596,12 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
 
        while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
                switch_size_t file_sample_len = samples;
-               switch_size_t file_data_len = samples * 2;
+               switch_size_t file_data_len = samples * 2 * conference->channels;
                int has_file_data = 0, members_with_video = 0;
                uint32_t conf_energy = 0;
                int nomoh = 0;
-               conference_member_t *floor_holder, *video_bridge_members[2] = { 0 };
-               
+               conference_member_t *floor_holder, *video_bridge_members[2] = { 0 };            
+
                /* Sync the conference to a single timing source */
                if (switch_core_timer_next(&timer) != SWITCH_STATUS_SUCCESS) {
                        switch_set_flag(conference, CFLAG_DESTRUCT);
@@ -2744,11 +2745,13 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
                                conference->fnode->leadin--;
                        } else if (!conference->fnode->done) {
                                file_sample_len = samples;
+                               
                                if (conference->fnode->type == NODE_TYPE_SPEECH) {
                                        switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_BLOCKING;
-
+                                       
                                        if (switch_core_speech_read_tts(conference->fnode->sh, file_frame, &file_data_len, &flags) == SWITCH_STATUS_SUCCESS) {
-                                               file_sample_len = file_data_len / 2;
+                                               file_sample_len = file_data_len / 2 / conference->fnode->sh->channels;
+                                               
                                        } else {
                                                file_sample_len = file_data_len = 0;
                                        }
@@ -2780,8 +2783,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
                                } else {
                                        if (has_file_data) {
                                                switch_size_t x;
-
-                                               for (x = 0; x < file_sample_len; x++) {
+                                               for (x = 0; x < file_sample_len * conference->channels; x++) {
                                                        int32_t z;
                                                        int16_t *muxed;
 
@@ -2792,27 +2794,29 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
                                                        muxed[x] = (int16_t) z;
                                                }
                                        } else {
-                                               memcpy(file_frame, async_file_frame, file_sample_len * 2);
+                                               memcpy(file_frame, async_file_frame, file_sample_len * 2 * conference->channels);
                                                has_file_data = 1;
                                        }
                                }
                        }
                }
-
+               
                if (ready || has_file_data) {
                        /* Use more bits in the main_frame to preserve the exact sum of the audio samples. */
-                       int main_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
-                       int16_t write_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
+                       int main_frame[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
+                       int16_t write_frame[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
 
 
                        /* Init the main frame with file data if there is any. */
                        bptr = (int16_t *) file_frame;
                        if (has_file_data && file_sample_len) {
+
                                for (x = 0; x < bytes / 2; x++) {
-                                       if (x <= file_sample_len) {
+                                       if (x <= file_sample_len * conference->channels) {
                                                main_frame[x] = (int32_t) bptr[x];
                                        } else {
                                                memset(&main_frame[x], 255, sizeof(main_frame[x]));
+                                               //printf("FUCCCK %d <= %ld (%ld/%d)\n", x, file_sample_len * conference->channels, file_sample_len, conference->channels);
                                        }
                                }
                        }
@@ -2876,8 +2880,10 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
                                }
 
                                bptr = (int16_t *) omember->frame;
-                               for (x = 0; x < bytes / 2; x++) {
+                               
+                               for (x = 0; x < bytes / 2 ; x++) {
                                        z = main_frame[x];
+
                                        /* bptr[x] represents my own contribution to this audio sample */
                                        if (switch_test_flag(omember, MFLAG_HAS_AUDIO) && x <= omember->read / 2) {
                                                z -= (int32_t) bptr[x];
@@ -3678,6 +3684,27 @@ static void check_agc_levels(conference_member_t *member)
 }
 
 
+static void member_check_channels(switch_frame_t *frame, conference_member_t *member, switch_bool_t in)
+{
+       if (member->conference->channels != member->read_impl.number_of_channels) {
+               uint32_t rlen;
+               int from, to;
+
+               if (in) {
+                       to = member->conference->channels;
+                       from = member->read_impl.number_of_channels;
+               } else {
+                       from = member->conference->channels;
+                       to = member->read_impl.number_of_channels;
+               }
+
+               rlen = frame->datalen / 2 / from; 
+
+               switch_mux_channels((int16_t *) frame->data, rlen, from, to);
+
+               frame->datalen = rlen * 2 * to;
+       }
+}
 
 
 /* marshall frames from the call leg to the conference thread for muxing to other call legs */
@@ -3729,6 +3756,8 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
                        break;
                }
 
+               member_check_channels(read_frame, member, SWITCH_TRUE);
+               
                if (switch_channel_test_flag(channel, CF_VIDEO) && !switch_test_flag(member, MFLAG_ACK_VIDEO)) {
                        switch_set_flag_locked(member, MFLAG_ACK_VIDEO);
                        switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
@@ -3827,7 +3856,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
                                switch_change_sln_volume_granular(read_frame->data, read_frame->datalen / 2, member->agc_volume_in_level);
                        }
                        
-                       if ((samples = read_frame->datalen / sizeof(*data))) {
+                       if ((samples = read_frame->datalen / sizeof(*data) / member->read_impl.number_of_channels)) {
                                for (i = 0; i < samples; i++) {
                                        energy += abs(data[j]);
                                        j += member->read_impl.number_of_channels;
@@ -3980,9 +4009,9 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
                                int16_t *bptr = (int16_t *) read_frame->data;
                                int len = (int) read_frame->datalen;
 
-                               switch_resample_process(read_resampler, bptr, len / 2);
-                               memcpy(member->resample_out, read_resampler->to, read_resampler->to_len * 2);
-                               len = read_resampler->to_len * 2;
+                               switch_resample_process(read_resampler, bptr, len / 2 / member->conference->channels);
+                               memcpy(member->resample_out, read_resampler->to, read_resampler->to_len * 2 * member->conference->channels);
+                               len = read_resampler->to_len * 2 * member->conference->channels;
                                datalen = len;
                                data = member->resample_out;
                        } else {
@@ -4039,8 +4068,8 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v
 
 static void member_add_file_data(conference_member_t *member, int16_t *data, switch_size_t file_data_len)
 {
-       switch_size_t file_sample_len = file_data_len / 2;
-       int16_t file_frame[SWITCH_RECOMMENDED_BUFFER_SIZE / 2] = { 0 };
+       switch_size_t file_sample_len;
+       int16_t file_frame[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };
 
 
        switch_mutex_lock(member->fnode_mutex);
@@ -4049,6 +4078,8 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi
                goto done;
        }
 
+       file_sample_len = file_data_len / 2 / member->conference->channels;
+
        /* if we are done, clean it up */
        if (member->fnode->done) {
                conference_file_node_t *fnode;
@@ -4071,15 +4102,15 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi
                } else {
                        if (member->fnode->type == NODE_TYPE_SPEECH) {
                                switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_BLOCKING;
-
+                               
                                if (switch_core_speech_read_tts(member->fnode->sh, file_frame, &file_data_len, &flags) == SWITCH_STATUS_SUCCESS) {
-                                       file_sample_len = file_data_len / 2;
+                                       file_sample_len = file_data_len / 2 / member->conference->channels;
                                } else {
                                        file_sample_len = file_data_len = 0;
                                }
                        } else if (member->fnode->type == NODE_TYPE_FILE) {
                                switch_core_file_read(&member->fnode->fh, file_frame, &file_sample_len);
-                               file_data_len = file_sample_len * 2;
+                               file_data_len = file_sample_len * 2 * member->fnode->fh.channels;
                        }
 
                        if (file_sample_len <= 0) {
@@ -4092,7 +4123,7 @@ static void member_add_file_data(conference_member_t *member, int16_t *data, swi
                                        switch_change_sln_volume(file_frame, (uint32_t)file_sample_len, member->volume_out_level);
                                }
 
-                               for (i = 0; i < (int)file_sample_len; i++) {
+                               for (i = 0; i < (int)file_sample_len * member->conference->channels; i++) {
                                        if (member->fnode->mux) {
                                                sample = data[i] + file_frame[i];
                                                switch_normalize_to_16bit(sample);
@@ -4157,7 +4188,7 @@ static void conference_loop_output(conference_member_t *member)
        //csamples = samples;
        tsamples = member->orig_read_impl.samples_per_packet;
        low_count = 0;
-       bytes = samples * 2;
+       bytes = samples * 2 * member->conference->channels;
        call_list = NULL;
        cp = NULL;
 
@@ -4165,7 +4196,7 @@ static void conference_loop_output(conference_member_t *member)
 
        switch_assert(member->conference != NULL);
 
-       flush_len = switch_samples_per_packet(member->conference->rate, member->conference->interval) * 10;
+       flush_len = switch_samples_per_packet(member->conference->rate, member->conference->interval) * 10 * member->conference->channels;
 
        if (switch_core_timer_init(&timer, member->conference->timer_name, interval, tsamples, NULL) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Timer Setup Failed.  Conference Cannot Start\n");
@@ -4331,7 +4362,7 @@ static void conference_loop_output(conference_member_t *member)
                mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
                
                use_timer = 1;
-               
+
                if (mux_used) {
                        if (mux_used < bytes) {
                                if (++low_count >= 5) {
@@ -4354,7 +4385,7 @@ static void conference_loop_output(conference_member_t *member)
                        low_count = 0;
                        if ((write_frame.datalen = (uint32_t) switch_buffer_read(use_buffer, write_frame.data, bytes))) {
                                if (write_frame.datalen) {
-                                       write_frame.samples = write_frame.datalen / 2;
+                                       write_frame.samples = write_frame.datalen / 2 / member->conference->channels;
                                   
                                   if( !switch_test_flag(member, MFLAG_CAN_HEAR)) {
                                      memset(write_frame.data, 255, write_frame.datalen);
@@ -4369,6 +4400,9 @@ static void conference_loop_output(conference_member_t *member)
                                        if (member->fnode) {
                                                member_add_file_data(member, write_frame.data, write_frame.datalen);
                                        }
+
+                                       member_check_channels(&write_frame, member, SWITCH_FALSE);
+
                                        if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
                                                switch_mutex_unlock(member->audio_out_mutex);
                                                break;
@@ -4383,6 +4417,7 @@ static void conference_loop_output(conference_member_t *member)
                        memset(write_frame.data, 255, write_frame.datalen);
                        write_frame.timestamp = timer.samplecount;
                        member_add_file_data(member, write_frame.data, write_frame.datalen);
+                       member_check_channels(&write_frame, member, SWITCH_FALSE);
                        if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
                                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
                                break;
@@ -4399,6 +4434,8 @@ static void conference_loop_output(conference_member_t *member)
                        write_frame.samples = samples;
                        write_frame.timestamp = timer.samplecount;
                        
+                       member_check_channels(&write_frame, member, SWITCH_FALSE);
+
                        if (switch_core_session_write_frame(member->session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
                                switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
                                break;
@@ -4521,7 +4558,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
                return NULL;
        }
 
-       data_buf_len = samples * sizeof(int16_t);
+       data_buf_len = samples * sizeof(int16_t) * conference->channels;
        switch_zmalloc(data_buf, data_buf_len);
 
        switch_mutex_lock(globals.hash_mutex);
@@ -4574,7 +4611,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
        fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
 
        if (switch_core_file_open(&fh,
-                                                         rec->path, (uint8_t) 1, conference->rate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT,
+                                                         rec->path, (uint8_t) conference->channels, conference->rate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT,
                                                          rec->pool) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening File [%s]\n", rec->path);
 
@@ -4917,7 +4954,7 @@ static switch_status_t conference_play_file(conference_obj_t *conference, char *
 
        /* Open the file */
        fnode->fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
-       if (switch_core_file_open(&fnode->fh, file, (uint8_t) 1, conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, pool) !=
+       if (switch_core_file_open(&fnode->fh, file, (uint8_t) conference->channels, conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, pool) !=
                SWITCH_STATUS_SUCCESS) {
                switch_event_t *event;
 
@@ -5043,7 +5080,7 @@ static switch_status_t conference_member_play_file(conference_member_t *member,
        /* Open the file */
        fnode->fh.pre_buffer_datalen = SWITCH_DEFAULT_FILE_BUFFER_LEN;
        if (switch_core_file_open(&fnode->fh,
-                                                         file, (uint8_t) 1, member->conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
+                                                         file, (uint8_t) member->conference->channels, member->conference->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT,
                                                          pool) != SWITCH_STATUS_SUCCESS) {
                switch_core_destroy_memory_pool(&pool);
                status = SWITCH_STATUS_NOTFOUND;
@@ -5109,7 +5146,7 @@ static switch_status_t conference_member_say(conference_member_t *member, char *
        if (!member->sh) {
                memset(&member->lsh, 0, sizeof(member->lsh));
                if (switch_core_speech_open(&member->lsh, conference->tts_engine, conference->tts_voice,
-                                                                       conference->rate, conference->interval, &flags, switch_core_session_get_pool(member->session)) !=
+                                                                       conference->rate, conference->interval, conference->channels, &flags, switch_core_session_get_pool(member->session)) !=
                        SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_ERROR, "Invalid TTS module [%s]!\n", conference->tts_engine);
                        return SWITCH_STATUS_FALSE;
@@ -5198,7 +5235,7 @@ static switch_status_t conference_say(conference_obj_t *conference, const char *
        if (!conference->sh) {
                memset(&conference->lsh, 0, sizeof(conference->lsh));
                if (switch_core_speech_open(&conference->lsh, conference->tts_engine, conference->tts_voice,
-                                                                       conference->rate, conference->interval, &flags, NULL) != SWITCH_STATUS_SUCCESS) {
+                                                                       conference->rate, conference->interval, conference->channels, &flags, NULL) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module [%s]!\n", conference->tts_engine);
                        return SWITCH_STATUS_FALSE;
                }
@@ -8075,14 +8112,15 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference
        if (switch_core_codec_init(&member->read_codec,
                                                           "L16",
                                                           NULL, read_impl.actual_samples_per_second, read_impl.microseconds_per_packet / 1000,
-                                                          1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
+                                                          read_impl.number_of_channels, 
+                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
-                                                 "Raw Codec Activation Success L16@%uhz 1 channel %dms\n",
-                                                 read_impl.actual_samples_per_second, read_impl.microseconds_per_packet / 1000);
+                                                 "Raw Codec Activation Success L16@%uhz %d channel %dms\n",
+                                                 read_impl.actual_samples_per_second, read_impl.number_of_channels, read_impl.microseconds_per_packet / 1000);
 
        } else {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n",
-                                                 read_impl.actual_samples_per_second, read_impl.microseconds_per_packet / 1000);
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz %d channel %dms\n",
+                                                 read_impl.actual_samples_per_second, read_impl.number_of_channels, read_impl.microseconds_per_packet / 1000);
 
                goto done;
        }
@@ -8096,7 +8134,7 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference
        if (read_impl.actual_samples_per_second != conference->rate) {
                if (switch_resample_create(&member->read_resampler,
                                                                   read_impl.actual_samples_per_second,
-                                                                  conference->rate, member->frame_size, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) {
+                                                                  conference->rate, member->frame_size, SWITCH_RESAMPLE_QUALITY, conference->channels) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_CRIT, "Unable to create resampler!\n");
                        goto done;
                }
@@ -8120,12 +8158,14 @@ static int setup_media(conference_member_t *member, conference_obj_t *conference
                                                           NULL,
                                                           conference->rate,
                                                           read_impl.microseconds_per_packet / 1000,
-                                                          1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
+                                                          read_impl.number_of_channels, 
+                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, member->pool) == SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
-                                                 "Raw Codec Activation Success L16@%uhz 1 channel %dms\n", conference->rate, read_impl.microseconds_per_packet / 1000);
+                                                 "Raw Codec Activation Success L16@%uhz %d channel %dms\n", 
+                                                 conference->rate, conference->channels, read_impl.microseconds_per_packet / 1000);
        } else {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz 1 channel %dms\n",
-                                                 conference->rate, read_impl.microseconds_per_packet / 1000);
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG, "Raw Codec Activation Failed L16@%uhz %d channel %dms\n",
+                                                 conference->rate, conference->channels, read_impl.microseconds_per_packet / 1000);
                goto codec_done2;
        }
 
@@ -9027,6 +9067,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
        uint32_t announce_count = 0;
        char *maxmember_sound = NULL;
        uint32_t rate = 8000, interval = 20;
+       uint32_t channels = 1;
        int broadcast_chat_messages = 0;
        int comfort_noise_level = 0;
        int pin_retries = 3;
@@ -9044,8 +9085,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
        switch_uuid_t uuid;
        switch_codec_implementation_t read_impl = { 0 };
        switch_channel_t *channel = NULL;
-       const char *force_rate = NULL, *force_interval = NULL, *presence_id = NULL;
-       uint32_t force_rate_i = 0, force_interval_i = 0;
+       const char *force_rate = NULL, *force_interval = NULL, *force_channels = NULL, *presence_id = NULL;
+       uint32_t force_rate_i = 0, force_interval_i = 0, force_channels_i = NULL;
 
        /* Validate the conference name */
        if (zstr(name)) {
@@ -9073,6 +9114,18 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
                        }
                }
 
+               if ((force_channels = switch_channel_get_variable(channel, "conference_force_channels"))) {
+                       if (!strcasecmp(force_channels, "auto")) {
+                               force_rate_i = read_impl.number_of_channels;
+                       } else {
+                               tmp = atoi(force_channels);
+
+                               if (tmp == 1 || tmp == 2) {
+                                       force_channels_i = channels = tmp;
+                               }
+                       }
+               }
+
                if ((force_interval = switch_channel_get_variable(channel, "conference_force_interval"))) {
                        if (!strcasecmp(force_interval, "auto")) {
                                force_interval_i = read_impl.microseconds_per_packet / 1000;
@@ -9117,6 +9170,17 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
                                                rate = tmp;
                                        }
                                }
+                       } else if (!force_channels_i && !strcasecmp(var, "channels") && !zstr(val)) {
+                               uint32_t tmp = atoi(val);
+                               if (session && tmp == 0) {
+                                       if (!strcasecmp(val, "auto")) {
+                                               channels = read_impl.number_of_channels;
+                                       }
+                               } else {
+                                       if (tmp == 1 || tmp == 2) {
+                                               channels = tmp;
+                                       }
+                               }
                        } else if (!strcasecmp(var, "domain") && !zstr(val)) {
                                domain = val;
                        } else if (!strcasecmp(var, "description") && !zstr(val)) {
@@ -9507,6 +9571,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
                conference->domain = "cluecon.com";
        }
 
+       conference->channels = channels;
        conference->rate = rate;
        conference->interval = interval;
        conference->ivr_dtmf_timeout = ivr_dtmf_timeout;
index b00b7093546a361fb2d436455cdcf1fc5abf4b2a..c368c28b24529c323558dbfcc2b61561fece9407 100644 (file)
@@ -118,7 +118,7 @@ static swift_result_t write_audio(swift_event * event, swift_event_t type, void
        return rv;
 }
 
-static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, const char *voice_name, int rate, switch_speech_flag_t *flags)
+static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, const char *voice_name, int rate, int channels, switch_speech_flag_t *flags)
 {
        cepstral_t *cepstral = switch_core_alloc(sh->memory_pool, sizeof(*cepstral));
        char srate[25];
@@ -290,7 +290,6 @@ static switch_status_t cepstral_speech_read_tts(switch_speech_handle_t *sh, void
 
 
                if (!used && cepstral->done_gen) {
-
                        status = SWITCH_STATUS_BREAK;
                        break;
                }
index cb9b558a488195c362db273317f4923a55af1de0..af10ca337111164de7f67e5508a4223411ee99bc 100644 (file)
@@ -143,6 +143,11 @@ static switch_status_t switch_opus_fmtp_parse(const char *fmtp, switch_codec_fmt
                                                        codec_settings->samplerate = atoi(arg);
                                                        codec_fmtp->actual_samples_per_second = codec_settings->samplerate;
                                                }
+
+                                               if (!strcasecmp(data, "stereo")) {
+                                                       codec_settings->stereo = atoi(arg);
+                                                       codec_fmtp->stereo = codec_settings->stereo;
+                                               }
                         
                                                if (!strcasecmp(data, "maxaveragebitrate")) {
                                                        codec_settings->maxaveragebitrate = atoi(arg);
@@ -202,36 +207,40 @@ static char *gen_fmtp(opus_codec_settings_t *settings, switch_memory_pool_t *poo
        char buf[256] = "";
     
        if (settings->useinbandfec) {
-               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "useinbandfec=1;");
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "useinbandfec=1; ");
        }
     
        if (settings->usedtx) {
-               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "usedtx=1;");
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "usedtx=1; ");
        }
     
        if (settings->maxaveragebitrate) {
-               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxaveragebitrate=%d;", settings->maxaveragebitrate);
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxaveragebitrate=%d; ", settings->maxaveragebitrate);
         
        }
     
        if (settings->ptime) {
-               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ptime=%d;", settings->ptime);
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "ptime=%d; ", settings->ptime);
        }
     
        if (settings->minptime) {
-               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "minptime=%d;", settings->minptime);
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "minptime=%d; ", settings->minptime);
        }
-    
+
        if (settings->maxptime) {
-               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxptime=%d;", settings->maxptime);
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "maxptime=%d; ", settings->maxptime);
        }
     
        if (settings->samplerate) {
-               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "samplerate=%d;", settings->samplerate);
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "samplerate=%d; ", settings->samplerate);
        }
-    
-       if (end_of(buf) == ';') {
-               end_of(buf) = '\0';
+
+       if (settings->stereo) {
+               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "stereo=%d; ", settings->stereo);
+       }
+
+       if (end_of(buf) == ' ') {
+               *(end_of_p(buf) - 1) = '\0';
        }
        
        return switch_core_strdup(pool, buf);
@@ -255,9 +264,8 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
        memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
        codec_fmtp.private_info = &opus_codec_settings;
        switch_opus_fmtp_parse(codec->fmtp_in, &codec_fmtp);
-    
        codec->fmtp_out = gen_fmtp(&opus_codec_settings, codec->memory_pool);
-    
+
        if (encoding) {
                /* come up with a way to specify these */
                int bitrate_bps = OPUS_AUTO;
@@ -268,7 +276,7 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
         
                context->encoder_object = opus_encoder_create(samplerate,
                                                                                                          codec->implementation->number_of_channels,
-                                                                                                         OPUS_APPLICATION_VOIP, &err);
+                                                                                                         codec->implementation->number_of_channels == 1 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO, &err);
         
         if (err != OPUS_OK) {
             switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create encoder: %s\n", opus_strerror(err));
@@ -358,17 +366,19 @@ static switch_status_t switch_opus_encode(switch_codec_t *codec,
        if (!context) {
                return SWITCH_STATUS_FALSE;
        }
-    
-       if (len > 1275) len = 1275;
-    
-       bytes = opus_encode(context->encoder_object, (void *) decoded_data, decoded_data_len / 2, (unsigned char *) encoded_data, len);
-    
+
+       if (len > 2880) len = 2880;
+
+       bytes = opus_encode(context->encoder_object, (void *) decoded_data, 
+                                               decoded_data_len / 2 / codec->implementation->number_of_channels, (unsigned char *) encoded_data, len);
+
        if (bytes > 0) {
                *encoded_data_len = (uint32_t) bytes;
                return SWITCH_STATUS_SUCCESS;
        }
-    
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Error!\n");
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Error: %s Decoded Datalen %u Codec NumberChans %u Len %u DecodedDate %p EncodedData %p ContextEncoderObject %p!\n", opus_strerror(bytes),decoded_data_len,codec->implementation->number_of_channels,len,(void *) decoded_data,(void *) encoded_data,(void *) context->encoder_object);
+
        return SWITCH_STATUS_GENERR;
 }
 
@@ -387,12 +397,13 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec,
        }
        
        samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, *decoded_data_len, 0);
-    
+
        if (samples < 0) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error: %s!\n", opus_strerror(samples));
                return SWITCH_STATUS_GENERR;
        }
-    
-       *decoded_data_len = samples * 2;
+
+       *decoded_data_len = samples * 2 * codec->implementation->number_of_channels;
        
        return SWITCH_STATUS_SUCCESS;
 }
@@ -481,6 +492,27 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
                                                                                         switch_opus_decode,    /* function to decode encoded data into raw data */
                                                                                         switch_opus_destroy);  /* deinitalize a codec handle using this implementation */
                
+               settings.stereo = 1;
+               dft_fmtp = gen_fmtp(&settings, pool);
+
+               switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
+                                                                                        116,   /* the IANA code number */
+                                                                                        "opus",/* the IANA code name */
+                                                                                        dft_fmtp,      /* default fmtp to send (can be overridden by the init function) */
+                                                                                        rate,  /* samples transferred per second */
+                                                                                        rate,  /* actual samples transferred per second */
+                                                                                        bits,  /* bits transferred per second */
+                                                                                        mss,   /* number of microseconds per frame */
+                                                                                        samples,       /* number of samples per frame */
+                                                                                        bytes * 2,     /* number of bytes per frame decompressed */
+                                                                                        0,     /* number of bytes per frame compressed */
+                                                                                        2,/* number of channels represented */
+                                                                                        1,     /* number of frames per network packet */
+                                                                                        switch_opus_init,      /* function to initialize a codec handle using this implementation */
+                                                                                        switch_opus_encode,    /* function to encode raw data into encoded data */
+                                                                                        switch_opus_decode,    /* function to decode encoded data into raw data */
+                                                                                        switch_opus_destroy);  /* deinitalize a codec handle using this implementation */
+
                bytes *= 2;
                samples *= 2;
                mss *= 2;
index 35ea59d8411837f7da7c95c2e0f7ca76dd5a9a1a..5f4a1e064530db13afb99b1f96c846316d6822f4 100644 (file)
@@ -298,7 +298,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
                                                        }
                                                }
 
-                                               switch_buffer_write(audio_buffer, abuf, olen * 2);
+                                               switch_buffer_write(audio_buffer, abuf, olen * 2 * source->channels);
                                        }
                                }
 
@@ -308,8 +308,8 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
                                        break;
                                }
 
-                               if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) {
-                                       used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2);
+                               if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
+                                       used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);
                                        if (source->total) {
                                                uint32_t bused = 0;
                                                switch_mutex_lock(source->mutex);
@@ -548,7 +548,7 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void
 {
        local_stream_context_t *context = handle->private_info;
        switch_size_t bytes = 0;
-       size_t need = *len * 2;
+       size_t need = *len * 2 * handle->real_channels;
 
        if (!context->source->ready) {
                *len = 0;
@@ -557,13 +557,13 @@ static switch_status_t local_stream_file_read(switch_file_handle_t *handle, void
 
        switch_mutex_lock(context->audio_mutex);
        if ((bytes = switch_buffer_read(context->audio_buffer, data, need))) {
-               *len = bytes / 2;
+               *len = bytes / 2 / handle->real_channels;
        } else {
                if (need > 2560) {
                        need = 2560;
                }
                memset(data, 255, need);
-               *len = need / 2;
+               *len = need / 2 / handle->real_channels;
        }
        switch_mutex_unlock(context->audio_mutex);
        handle->sample_count += *len;
index 4c41e2e63ae5a4a8cf17ea2926b20973c29ac12e..07e0e41ce7693dd1f1553b6d6e15e91af4aed125 100644 (file)
@@ -99,6 +99,8 @@ static switch_status_t shell_stream_file_open(switch_file_handle_t *handle, cons
                return SWITCH_STATUS_FALSE;
        }
 
+       handle->channels = 1;
+
        context = switch_core_alloc(handle->memory_pool, sizeof(*context));
 
        context->fds[0] = -1;
index 662de882c3ab559fb016f51f3847189883a798d3..68ea6b77b0bc0b7d6dc6ccf0d4da8066969348d0 100644 (file)
@@ -625,6 +625,9 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
        char *err = NULL;
        const char *mpg123err = NULL;
        int portno = 0;
+       long rate = 0;
+       int channels = 0;
+       int encoding = 0;
 
        if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
                return SWITCH_STATUS_MEMERR;
@@ -659,9 +662,6 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
                }
 
                if (handle->handler) {
-                       if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_MONO_MIX, 0) != MPG123_OK) {
-                               MPGERROR();
-                       }
                        if (mpg123_open_feed(context->mh) != MPG123_OK) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening mpg feed\n");
                                mpg123err = mpg123_strerror(context->mh);
@@ -672,9 +672,7 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
                        launch_read_stream_thread(context);
                } else {
                        handle->seekable = 1;
-                       if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_MONO_MIX, 0) != MPG123_OK) {
-                               MPGERROR();
-                       }
+
                        if (mpg123_open(context->mh, path) != MPG123_OK) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
                                mpg123err = mpg123_strerror(context->mh);
@@ -682,6 +680,12 @@ static switch_status_t shout_file_open(switch_file_handle_t *handle, const char
                        }
 
                }
+
+
+               mpg123_getformat(context->mh, &rate, &channels, &encoding);
+               handle->channels = channels;
+               handle->samplerate = rate;
+
        } else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
                if (!(context->gfp = lame_init())) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
@@ -897,7 +901,7 @@ static switch_status_t shout_file_seek(switch_file_handle_t *handle, unsigned in
 static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data, size_t *len)
 {
        shout_context_t *context = handle->private_info;
-       size_t rb = 0, bytes = *len * sizeof(int16_t), newbytes = 0;
+       size_t rb = 0, bytes = *len * sizeof(int16_t) * handle->channels, newbytes = 0;
 
        *len = 0;
 
@@ -919,7 +923,7 @@ static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data,
        /* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "rb: %d, bytes: %d\n", (int) rb, (int) bytes); */
 
        if (rb) {
-               *len = rb / sizeof(int16_t);
+               *len = rb / sizeof(int16_t) / handle->channels;
        } else {
                /* no data, so insert 1 second of silence */
                newbytes = 2 * handle->samplerate;
@@ -929,7 +933,7 @@ static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data,
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Padding mp3 stream with 1s of empty audio. (%s)\n", context->stream_url);
 
                memset(data, 255, bytes);
-               *len = bytes / sizeof(int16_t);
+               *len = bytes / sizeof(int16_t) / handle->channels;
        }
 
        handle->sample_count += *len;
index 3c6e69ac8e3a7477daed5e23f2d7b2ccc3dfc639..06a5de98c2421560ba5b2a0ce2a457f28fe2416a 100644 (file)
@@ -67,6 +67,7 @@ static switch_status_t silence_stream_file_open(switch_file_handle_t *handle, co
                }
        }
 
+       handle->channels = 1;
        handle->private_info = sh;
 
        return SWITCH_STATUS_SUCCESS;
@@ -153,6 +154,8 @@ static switch_status_t tone_stream_file_open(switch_file_handle_t *handle, const
                handle->samplerate = 8000;
        }
 
+       handle->channels = 1;
+
        teletone_init_session(&ts, 0, teletone_handler, audio_buffer);
        ts.rate = handle->samplerate;
        ts.channels = 1;
index 24488f8899690ba8e9e77e215e51f45ee6efa6b0..51996686dcfc2cac77aceba84cceb97d0e462474 100644 (file)
@@ -73,6 +73,7 @@ struct vlc_file_context {
        int samples;
        int playing;
        int samplerate;
+       int channels;
        int err;
        int pts;
        libvlc_instance_t *inst_out;
@@ -113,7 +114,7 @@ void vlc_auto_play_callback(void *data, const void *samples, unsigned count, int
        
        switch_mutex_lock(context->audio_mutex);
        if (context->audio_buffer) {
-               if (!switch_buffer_write(context->audio_buffer, samples, count * 2)) {
+               if (!switch_buffer_write(context->audio_buffer, samples, count * 2 * context->channels)) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer error\n");
                }
        }
@@ -145,7 +146,7 @@ int  vlc_imem_get_callback(void *data, const char *cookie, int64_t *dts, int64_t
        context->samples = 0;
        
        if ( samples ) {
-               bytes = samples * 2;
+               bytes = samples * 2 * context->channels;
                *output = malloc(bytes);
                bytes = switch_buffer_read(context->audio_buffer, *output, bytes);
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC imem samples: %d\n", samples);
@@ -210,12 +211,14 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
                
                context->mp = libvlc_media_player_new_from_media(context->m);
                
-               if ( !handle->samplerate)
+               if (!handle->samplerate) {
                        handle->samplerate = 16000;
+               }
 
                context->samplerate = handle->samplerate;
-               
-               libvlc_audio_set_format(context->mp, "S16N", context->samplerate, 1);
+               context->channels = handle->channels;
+
+               libvlc_audio_set_format(context->mp, "S16N", context->samplerate, handle->channels);
                
                m_event_manager = libvlc_media_event_manager(context->m);
                libvlc_event_attach(m_event_manager, libvlc_MediaStateChanged, vlc_media_state_callback, (void *) context);
@@ -246,7 +249,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
                opts[6] = "--rawaud-fourcc=s16l";
                opts[7] = switch_mprintf("--rawaud-samplerate=%d", context->samplerate);
                opts[8] = switch_mprintf("--imem-data=%ld", context);
-               opts[9] = "--rawaud-channels=1";
+               //opts[9] = "--rawaud-channels=1";
 
                /* Prepare to write to an output stream. */
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for writing\n", path);
@@ -274,7 +277,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
 static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, size_t *len)
 {
        vlc_file_context_t *context = handle->private_info;
-       size_t bytes = *len * sizeof(int16_t), read;
+       size_t bytes = *len * sizeof(int16_t) * handle->channels, read;
        libvlc_state_t status;
        
        if (!context) {
@@ -310,7 +313,8 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
        read = switch_buffer_read(context->audio_buffer, data, bytes);
        switch_mutex_unlock(context->audio_mutex);
        
-        status = libvlc_media_get_state(context->m);
+       status = libvlc_media_get_state(context->m);
+
        if (!read && (status == libvlc_Stopped || status == libvlc_Ended || status == libvlc_Error)) {
                return SWITCH_STATUS_FALSE;
        } else if (!read) {
@@ -318,8 +322,9 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
                memset(data, 0, read);
        }
        
-       if (read)
-               *len = read/2;
+       if (read) {
+               *len = read / 2 / handle->channels;
+       }
        
        return SWITCH_STATUS_SUCCESS;
 }
@@ -327,7 +332,7 @@ static switch_status_t vlc_file_read(switch_file_handle_t *handle, void *data, s
 static switch_status_t vlc_file_write(switch_file_handle_t *handle, void *data, size_t *len)
 {
        vlc_file_context_t *context = handle->private_info;
-       size_t bytes = *len * sizeof(int16_t);
+       size_t bytes = *len * sizeof(int16_t) * handle->channels;
        
        switch_mutex_lock(context->audio_mutex);
        context->samples += *len;
index eeaef7894c6b1301adcf16fd9bad837c5e2d2455..dce66a053deedfecd330ddde4729b3ed7d45d417 100644 (file)
@@ -982,7 +982,7 @@ switch_status_t FSSession::InitSpeechEngine(const char *engine, const char *voic
                return SWITCH_STATUS_FALSE;
        }
 
-       if (switch_core_speech_open(&this->_speech->sh, engine, voice, rate, interval,
+       if (switch_core_speech_open(&this->_speech->sh, engine, voice, rate, interval, read_codec->implementation->number_of_channels,
                                                                &flags, switch_core_session_get_pool(this->_session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n");
                switch_core_codec_destroy(&this->_speech->codec);
index 4b47e27c0f57cf7f988f1aff7d03ba1c61009529..63e33ec2b6104305ed421be43c8a0ea4d616c864 100644 (file)
@@ -700,8 +700,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_init_with_bitrate(switch_codec
                switch_set_flag(codec, SWITCH_CODEC_FLAG_READY);
                return SWITCH_STATUS_SUCCESS;
        } else {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms\n", codec_name, rate,
-                                                 ms);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms %dch\n", 
+                                                 codec_name, rate, ms, channels);
+                                                 
        }
 
        UNPROTECT_INTERFACE(codec_interface);
@@ -765,7 +766,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_decode(switch_codec_t *codec,
        }
 
        if (codec->implementation->encoded_bytes_per_packet) {
-               uint32_t frames = encoded_data_len / codec->implementation->encoded_bytes_per_packet;
+               uint32_t frames = encoded_data_len / codec->implementation->encoded_bytes_per_packet / codec->implementation->number_of_channels;
 
                if (frames && codec->implementation->decoded_bytes_per_packet * frames > *decoded_data_len) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Buffer size sanity check failed! edl:%u ebpp:%u fr:%u ddl:%u\n", 
index 3c6a2f8494e62158fdda022121e21ff84a3cd525..66e5df1d6e85aa10059e0ddafeb66a137eb34c96 100644 (file)
@@ -188,6 +188,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
                switch_goto_status(status, fail);
        }
 
+       fh->real_channels = fh->channels;
+
+       if (channels) {
+               fh->channels = channels;
+       }
 
        if ((flags & SWITCH_FILE_FLAG_WRITE) && !is_stream && (status = switch_file_exists(file_path, fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] not created!\n", file_path);
@@ -216,12 +221,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file,
 
        if (fh->pre_buffer_datalen) {
                //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Prebuffering %d bytes\n", (int)fh->pre_buffer_datalen);
-               switch_buffer_create_dynamic(&fh->pre_buffer, fh->pre_buffer_datalen * fh->channels, fh->pre_buffer_datalen * fh->channels / 2, 0);
+               switch_buffer_create_dynamic(&fh->pre_buffer, fh->pre_buffer_datalen * fh->channels, fh->pre_buffer_datalen * fh->channels, 0);
                fh->pre_buffer_data = switch_core_alloc(fh->memory_pool, fh->pre_buffer_datalen * fh->channels);
        }
 
-       if (fh->channels > 1 && (flags & SWITCH_FILE_FLAG_READ) && !(fh->flags & SWITCH_FILE_NOMUX)) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File has %d channels, muxing to mono will occur.\n", fh->channels);
+
+       if (fh->real_channels != fh->channels && (flags & SWITCH_FILE_FLAG_READ) && !(fh->flags & SWITCH_FILE_NOMUX)) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File has %d channels, muxing to %d channel%s will occur.\n", fh->real_channels, fh->channels, fh->channels == 1 ? "" : "s");
        }
 
        switch_set_flag(fh, SWITCH_FILE_OPEN);
@@ -264,8 +270,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh,
                return SWITCH_STATUS_FALSE;
        }
 
-       if (fh->buffer && switch_buffer_inuse(fh->buffer) >= *len * 2) {
-               *len = switch_buffer_read(fh->buffer, data, orig_len * 2) / 2;
+       if (fh->buffer && switch_buffer_inuse(fh->buffer) >= *len * 2 * fh->channels) {
+               *len = switch_buffer_read(fh->buffer, data, orig_len * 2 * fh->channels) / 2 / fh->channels;
                return *len == 0 ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
        }
 
@@ -284,9 +290,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh,
                int asis = switch_test_flag(fh, SWITCH_FILE_NATIVE);
 
                if (!switch_test_flag(fh, SWITCH_FILE_BUFFER_DONE)) {
-                       rlen = asis ? fh->pre_buffer_datalen : fh->pre_buffer_datalen / 2;
+                       rlen = asis ? fh->pre_buffer_datalen : fh->pre_buffer_datalen / 2 / fh->real_channels;
 
-                       if (switch_buffer_inuse(fh->pre_buffer) < rlen * 2) {
+                       if (switch_buffer_inuse(fh->pre_buffer) < rlen * 2 * fh->channels) {
                                if ((status = fh->file_interface->file_read(fh, fh->pre_buffer_data, &rlen)) == SWITCH_STATUS_BREAK) {
                                        return SWITCH_STATUS_BREAK;
                                }
@@ -296,16 +302,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh,
                                        switch_set_flag(fh, SWITCH_FILE_BUFFER_DONE);
                                } else {
                                        fh->samples_in += rlen;
-                                       if (fh->channels > 1 && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) {
-                                               switch_mux_channels((int16_t *) fh->pre_buffer_data, rlen, fh->channels);
+                                       if (fh->real_channels != fh->channels && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) {
+                                               switch_mux_channels((int16_t *) fh->pre_buffer_data, rlen, fh->real_channels, fh->channels);
                                        }
-                                       switch_buffer_write(fh->pre_buffer, fh->pre_buffer_data, asis ? rlen : rlen * 2);
+                                       switch_buffer_write(fh->pre_buffer, fh->pre_buffer_data, asis ? rlen : rlen * 2 * fh->channels);
                                }
                        }
                }
 
-               rlen = switch_buffer_read(fh->pre_buffer, data, asis ? *len : *len * 2);
-               *len = asis ? rlen : rlen / 2;
+               rlen = switch_buffer_read(fh->pre_buffer, data, asis ? *len : *len * 2 * fh->channels);
+               *len = asis ? rlen : rlen / 2 / fh->channels;
 
                if (*len == 0) {
                        switch_set_flag(fh, SWITCH_FILE_DONE);
@@ -327,23 +333,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh,
 
                fh->samples_in += *len;
 
-               if (fh->channels > 1 && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) {
-                       switch_mux_channels((int16_t *) data, *len, fh->channels);
+               if (fh->real_channels != fh->channels && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) {
+                       switch_mux_channels((int16_t *) data, *len, fh->real_channels, fh->channels);
                }
-
        }
 
-
        if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->native_rate != fh->samplerate) {
                if (!fh->resampler) {
                        if (switch_resample_create(&fh->resampler,
-                                                                          fh->native_rate, fh->samplerate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) {
+                                                                          fh->native_rate, fh->samplerate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, fh->channels) != SWITCH_STATUS_SUCCESS) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
                                return SWITCH_STATUS_GENERR;
                        }
                }
 
-               switch_resample_process(fh->resampler, data, (uint32_t) * len);
+               switch_resample_process(fh->resampler, data, (uint32_t) *len);
 
                if (fh->resampler->to_len < want || fh->resampler->to_len > orig_len) {
                        if (!fh->buffer) {
@@ -351,24 +355,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh,
                                switch_buffer_create_dynamic(&fh->buffer, factor, factor, 0);
                                switch_assert(fh->buffer);
                        }
-                       if (!fh->dbuf || fh->dbuflen < fh->resampler->to_len * 2) {
+                       if (!fh->dbuf || fh->dbuflen < fh->resampler->to_len * 2 * fh->channels) {
                                void *mem;
-                               fh->dbuflen = fh->resampler->to_len * 2;
+                               fh->dbuflen = fh->resampler->to_len * 2 * fh->channels;
                                mem = realloc(fh->dbuf, fh->dbuflen);
                                switch_assert(mem);
                                fh->dbuf = mem;
                        }
-                       switch_assert(fh->resampler->to_len * 2 <= fh->dbuflen);
-                       memcpy((int16_t *) fh->dbuf, fh->resampler->to, fh->resampler->to_len * 2);
-                       switch_buffer_write(fh->buffer, fh->dbuf, fh->resampler->to_len * 2);
+                       switch_assert(fh->resampler->to_len * 2 * fh->channels <= fh->dbuflen);
+                       memcpy((int16_t *) fh->dbuf, fh->resampler->to, fh->resampler->to_len * 2 * fh->channels);
+                       switch_buffer_write(fh->buffer, fh->dbuf, fh->resampler->to_len * 2 * fh->channels);
 
-                       if (switch_buffer_inuse(fh->buffer) < want * 2) {
+                       if (switch_buffer_inuse(fh->buffer) < want * 2 * fh->channels) {
                                *len = want;
                                goto more;
                        }
-                       *len = switch_buffer_read(fh->buffer, data, orig_len * 2) / 2;
+                       *len = switch_buffer_read(fh->buffer, data, orig_len * 2 * fh->channels) / 2 / fh->channels;
                } else {
-                       memcpy(data, fh->resampler->to, fh->resampler->to_len * 2);
+                       memcpy(data, fh->resampler->to, fh->resampler->to_len * 2 * fh->channels);
                        *len = fh->resampler->to_len;
                }
 
@@ -415,7 +419,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh,
                                switch_assert(mem);
                                fh->dbuf = mem;
                        }
-                       switch_assert(fh->resampler->to_len * 2 <= fh->dbuflen);
+                       switch_assert(fh->resampler->to_len * 2 *fh->channels <= fh->dbuflen);
                        memcpy(fh->dbuf, fh->resampler->to, fh->resampler->to_len * 2 * fh->channels);
                        data = fh->dbuf;
                } else {
index eb294a677319e9d037c49895bac00b84aa567dc9..430993df1f8f19311af27b575c518aabe39ef4a2 100644 (file)
@@ -596,6 +596,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
                                status = SWITCH_STATUS_RESAMPLE;
                        }
 
+                       /* mux or demux to match */
+                       if (session->read_impl.number_of_channels != read_frame->codec->implementation->number_of_channels) {
+                               uint32_t rlen = session->raw_read_frame.datalen / 2 / read_frame->codec->implementation->number_of_channels;
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s MUX READ\n", switch_channel_get_name(session->channel));
+                               switch_mux_channels((int16_t *) session->raw_read_frame.data, rlen, 
+                                                                       read_frame->codec->implementation->number_of_channels, session->read_impl.number_of_channels);
+                               session->raw_write_frame.datalen = rlen * 2 * session->read_impl.number_of_channels;
+                       }
+
                        switch (status) {
                        case SWITCH_STATUS_RESAMPLE:
                                if (!session->read_resampler) {
@@ -604,7 +613,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
                                        status = switch_resample_create(&session->read_resampler,
                                                                                                        read_frame->codec->implementation->actual_samples_per_second,
                                                                                                        session->read_impl.actual_samples_per_second,
-                                                                                                       session->read_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1);
+                                                                                                       session->read_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 
+                                                                                                       session->read_impl.number_of_channels);
 
                                        switch_mutex_unlock(session->resample_mutex);
 
@@ -807,10 +817,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
                        if (session->read_resampler) {
                                short *data = read_frame->data;
                                switch_mutex_lock(session->resample_mutex);
-                               switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2);
-                               memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2);
+                               switch_resample_process(session->read_resampler, data, (int) read_frame->datalen / 2 / session->read_resampler->channels);
+                               memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2 * session->read_resampler->channels);
                                read_frame->samples = session->read_resampler->to_len;
-                               read_frame->datalen = session->read_resampler->to_len * 2;
+                               read_frame->datalen = session->read_resampler->to_len * 2 * session->read_resampler->channels;
                                read_frame->rate = session->read_resampler->to_rate;
                                switch_mutex_unlock(session->resample_mutex);
                        }
@@ -1206,6 +1216,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
                        status = SWITCH_STATUS_RESAMPLE;
                }
                
+               /* mux or demux to match */
+               if (session->write_impl.number_of_channels != frame->codec->implementation->number_of_channels) {
+                       uint32_t rlen = session->raw_write_frame.datalen / 2 / frame->codec->implementation->number_of_channels;
+                       switch_mux_channels((int16_t *) session->raw_write_frame.data, rlen, 
+                                                               frame->codec->implementation->number_of_channels, session->write_impl.number_of_channels);
+                       session->raw_write_frame.datalen = rlen * 2 * session->write_impl.number_of_channels;
+               }
+               
                switch (status) {
                case SWITCH_STATUS_RESAMPLE:
                        resample++;
@@ -1216,7 +1234,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
                                status = switch_resample_create(&session->write_resampler,
                                                                                                frame->codec->implementation->actual_samples_per_second,
                                                                                                session->write_impl.actual_samples_per_second,
-                                                                                               session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1);
+                                                                                               session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, session->write_impl.number_of_channels);
 
 
                                switch_mutex_unlock(session->resample_mutex);
@@ -1294,13 +1312,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
                switch_mutex_lock(session->resample_mutex);
                if (session->write_resampler) {
 
-                       switch_resample_process(session->write_resampler, data, write_frame->datalen / 2);
+                       switch_resample_process(session->write_resampler, data, write_frame->datalen / 2 / session->write_resampler->channels);
 
-                       memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2);
+                       memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2 * session->write_resampler->channels);
 
                        write_frame->samples = session->write_resampler->to_len;
 
-                       write_frame->datalen = write_frame->samples * 2;
+                       write_frame->datalen = write_frame->samples * 2 * session->write_resampler->channels;
 
                        write_frame->rate = session->write_resampler->to_rate;
 
@@ -1527,7 +1545,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
                                                        status = switch_resample_create(&session->write_resampler,
                                                                                                                        frame->codec->implementation->actual_samples_per_second,
                                                                                                                        session->write_impl.actual_samples_per_second,
-                                                                                                                       session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 1);
+                                                                                                                       session->write_impl.decoded_bytes_per_packet, SWITCH_RESAMPLE_QUALITY, 
+                                                                                                                       session->write_impl.number_of_channels);
                                                }
                                                switch_mutex_unlock(session->resample_mutex);
 
@@ -1598,10 +1617,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
                                        short *data = write_frame->data;
                                        switch_mutex_lock(session->resample_mutex);
                                        if (session->read_resampler) {
-                                               switch_resample_process(session->read_resampler, data, write_frame->datalen / 2);
-                                               memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2);
+                                               switch_resample_process(session->read_resampler, data, write_frame->datalen / 2 / session->read_resampler->channels);
+                                               memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2 * session->read_resampler->channels);
                                                write_frame->samples = session->read_resampler->to_len;
-                                               write_frame->datalen = session->read_resampler->to_len * 2;
+                                               write_frame->datalen = session->read_resampler->to_len * 2 * session->read_resampler->channels;
                                                write_frame->rate = session->read_resampler->to_rate;
                                        }
                                        switch_mutex_unlock(session->resample_mutex);
index 82cc3c75c2bbf18dd1e4093e1a9016807f97c3cf..95403dbf42a47f023a74960e1c85d36f9c8e9238 100644 (file)
@@ -39,7 +39,8 @@
 SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t *sh,
                                                                                                                const char *module_name,
                                                                                                                const char *voice_name,
-                                                                                                               unsigned int rate, unsigned int interval, switch_speech_flag_t *flags, switch_memory_pool_t *pool)
+                                                                                                               unsigned int rate, unsigned int interval, unsigned int channels,
+                                                                                                               switch_speech_flag_t *flags, switch_memory_pool_t *pool)
 {
        switch_status_t status;
        char buf[256] = "";
@@ -83,8 +84,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_open(switch_speech_handle_t *
        sh->samples = switch_samples_per_packet(rate, interval);
        sh->samplerate = rate;
        sh->native_rate = rate;
+       sh->channels = channels;
+       sh->real_channels = 1;
 
-       if ((status = sh->speech_interface->speech_open(sh, voice_name, rate, flags)) == SWITCH_STATUS_SUCCESS) {
+       if ((status = sh->speech_interface->speech_open(sh, voice_name, rate, channels, flags)) == SWITCH_STATUS_SUCCESS) {
                switch_set_flag(sh, SWITCH_SPEECH_FLAG_OPEN);
        } else {
                UNPROTECT_INTERFACE(sh->speech_interface);
@@ -205,7 +208,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle
 
        if (sh->buffer && (switch_buffer_inuse(sh->buffer) >= orig_len || switch_test_flag(sh, SWITCH_SPEECH_FLAG_DONE))) {
                if ((*datalen = switch_buffer_read(sh->buffer, data, orig_len))) {
-                       return SWITCH_STATUS_SUCCESS;
+                       status = SWITCH_STATUS_SUCCESS;
+                       goto done;
                }
        }
 
@@ -217,16 +221,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle
 
   more:
 
+       *datalen = orig_len / sh->channels;
+
        if ((status = sh->speech_interface->speech_read_tts(sh, data, datalen, flags)) != SWITCH_STATUS_SUCCESS) {
                switch_set_flag(sh, SWITCH_SPEECH_FLAG_DONE);
                goto top;
        }
 
-
        if (sh->native_rate && sh->samplerate && sh->native_rate != sh->samplerate) {
                if (!sh->resampler) {
                        if (switch_resample_create(&sh->resampler,
-                                                                          sh->native_rate, sh->samplerate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) {
+                                                                          sh->native_rate, sh->samplerate, (uint32_t) orig_len / sh->channels, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
                                return SWITCH_STATUS_GENERR;
                        }
@@ -261,6 +266,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_speech_read_tts(switch_speech_handle
                }
        }
 
+
+ done:
+
+       if (sh->channels != sh->real_channels) {
+               uint32_t rlen = *datalen / 2;
+               switch_mux_channels((int16_t *) data, rlen, 1, sh->channels);
+               *datalen = rlen * 2 * sh->channels;
+       }
+       
        return status;
 
 }
index 9a69776380f2fc7933ed64f5c60044bd9777daca..00a933efcd31e019e4b041338947b644e363f1d8 100644 (file)
@@ -767,7 +767,7 @@ static switch_bool_t write_displace_callback(switch_media_bug_t *bug, void *user
 
                                st = switch_core_file_read(&dh->fh, buf, &len);
 
-                               for (x = 0; x < (uint32_t) len; x++) {
+                               for (x = 0; x < (uint32_t) len * dh->fh.channels; x++) {
                                        int32_t mixed = fp[x] + buf[x];
                                        switch_normalize_to_16bit(mixed);
                                        fp[x] = (int16_t) mixed;
@@ -779,6 +779,9 @@ static switch_bool_t write_displace_callback(switch_media_bug_t *bug, void *user
                                }
                        }
 
+                       rframe->datalen = rframe->samples * 2 * dh->fh.channels;
+
+
                        if (st != SWITCH_STATUS_SUCCESS || len == 0) {
                                if (dh->loop) {
                                        uint32_t pos = 0;
@@ -848,17 +851,20 @@ static switch_bool_t read_displace_callback(switch_media_bug_t *bug, void *user_
 
                                st = switch_core_file_read(&dh->fh, buf, &len);
 
-                               for (x = 0; x < (uint32_t) len; x++) {
+                               for (x = 0; x < (uint32_t) len * dh->fh.channels; x++) {
                                        int32_t mixed = fp[x] + buf[x];
                                        switch_normalize_to_16bit(mixed);
                                        fp[x] = (int16_t) mixed;
                                }
+                               
                        } else {
                                st = switch_core_file_read(&dh->fh, rframe->data, &len);
                                rframe->samples = (uint32_t) len;
-                               rframe->datalen = rframe->samples * 2;
                        }
 
+                       rframe->datalen = rframe->samples * 2 * dh->fh.channels;
+
+
                        if (st != SWITCH_STATUS_SUCCESS || len == 0) {
                                if (dh->loop) {
                                        uint32_t pos = 0;
index b07aee0ef00b3be33de4814456636eb20b73a7cf..9ac573d5dd3f527172f708df2c67b17989528832 100644 (file)
@@ -737,13 +737,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
 
                if (!switch_test_flag(fh, SWITCH_FILE_PAUSE) && !switch_test_flag(read_frame, SFF_CNG)) {
                        int16_t *data = read_frame->data;
-                       len = (switch_size_t) asis ? read_frame->datalen : read_frame->datalen / 2;
+                       len = (switch_size_t) asis ? read_frame->datalen : read_frame->datalen / 2 / fh->channels;
 
                        if (switch_core_file_write(fh, data, &len) != SWITCH_STATUS_SUCCESS) {
                                break;
                        }
                } else if (switch_test_flag(read_frame, SFF_CNG) && fill_cng) {
-                       len = write_frame.datalen / 2;
+                       len = write_frame.datalen / 2 / fh->channels;
                        if (switch_core_file_write(fh, write_frame.data, &len) != SWITCH_STATUS_SUCCESS) {
                                break;
                        }
@@ -1301,14 +1301,17 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
                                                                           codec_name,
                                                                           NULL,
                                                                           fh->samplerate,
-                                                                          interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
+                                                                          interval, read_impl.number_of_channels, 
+                                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, pool) == SWITCH_STATUS_SUCCESS) {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session),
-                                                                 SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
+                                                                 SWITCH_LOG_DEBUG, "Codec Activated %s@%uhz %u channels %dms\n", 
+                                                                 codec_name, fh->samplerate, read_impl.number_of_channels, interval);
 
 
                        } else {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
-                                                                 "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, fh->samplerate, fh->channels, interval);
+                                                                 "Raw Codec Activation Failed %s@%uhz %u channels %dms\n", codec_name, 
+                                                                 fh->samplerate, read_impl.number_of_channels, interval);
                                switch_core_session_io_write_lock(session);
                                switch_channel_set_private(channel, "__fh", NULL);
                                switch_core_session_io_rwunlock(session);
@@ -1339,7 +1342,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
                        uint32_t len;
 
                        len = samples * 2;
-                       if (switch_core_timer_init(&timer, timer_name, interval, samples, pool) != SWITCH_STATUS_SUCCESS) {
+                       if (switch_core_timer_init(&timer, timer_name, interval, samples / codec.implementation->number_of_channels, pool) != SWITCH_STATUS_SUCCESS) {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Setup timer failed!\n");
                                switch_core_codec_destroy(&codec);
                                switch_core_session_io_write_lock(session);
@@ -1351,7 +1354,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
                                continue;
                        }
                        switch_core_timer_sync(&timer); // Sync timer
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setup timer success %u bytes per %d ms!\n", len, interval);
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
+                                                         "Setup timer success %u bytes per %d ms! %d ch\n", len, interval, codec.implementation->number_of_channels);
                }
                write_frame.rate = fh->samplerate;
 
@@ -1445,7 +1449,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
                                }
                        }
 
-                       buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->cur_channels;
+                       buflen = FILE_STARTSAMPLES * sizeof(*abuf) * fh->cur_channels ? fh->cur_channels : fh->channels;
 
                        if (buflen > write_frame.buflen) {
                                abuf = realloc(abuf, buflen);
@@ -1502,10 +1506,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
                                        olen /= 2;
                                }
                                switch_set_flag(fh, SWITCH_FILE_BREAK_ON_CHANGE);
+                               
                                if ((rstatus = switch_core_file_read(fh, abuf, &olen)) == SWITCH_STATUS_BREAK) {
                                        continue;
                                }
-
+                               
                                if (rstatus != SWITCH_STATUS_SUCCESS) {
                                        eof++;
                                        continue;
@@ -1528,7 +1533,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
 
                                last_native = test_native;
 
-                               switch_buffer_write(fh->audio_buffer, abuf, switch_test_flag(fh, SWITCH_FILE_NATIVE) ? olen : olen * 2);
+                               switch_buffer_write(fh->audio_buffer, abuf, switch_test_flag(fh, SWITCH_FILE_NATIVE) ? olen : olen * 2 * fh->channels);
                                olen = switch_buffer_read(fh->audio_buffer, abuf, framelen);
                                fh->offset_pos += (uint32_t)(olen / 2);
 
@@ -2142,14 +2147,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
                                                                                                                         switch_codec_t *codec, switch_timer_t *timer, char *text, switch_input_args_t *args)
 {
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       short abuf[960];
+       short abuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
        switch_dtmf_t dtmf = { 0 };
        uint32_t len = 0;
        switch_size_t ilen = 0;
        switch_frame_t write_frame = { 0 };
-       int x;
        int done = 0;
-       int lead_in_out = 10;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
        switch_speech_flag_t flags = SWITCH_SPEECH_FLAG_NONE;
        switch_size_t extra = 0;
@@ -2174,7 +2177,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
        write_frame.data = abuf;
        write_frame.buflen = sizeof(abuf);
 
-       len = sh->samples * 2;
+       len = sh->samples * 2 * sh->channels;
 
        flags = 0;
 
@@ -2227,7 +2230,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
        text = NULL;
 
        write_frame.rate = sh->rate;
-
        memset(write_frame.data, 0, len);
        write_frame.datalen = len;
        write_frame.samples = len / 2;
@@ -2235,23 +2237,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
 
        switch_assert(codec->implementation != NULL);
 
-       for (x = 0; !done && x < lead_in_out; x++) {
-               switch_yield(codec->implementation->microseconds_per_packet);
-               if (timer) {
-                       write_frame.timestamp = timer->samplecount;
-               }
-               if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
-                       done = 1;
-                       break;
-               }
-       }
-
        switch_channel_audio_sync(channel);
 
-       ilen = len;
+
        for (;;) {
                switch_event_t *event;
 
+               ilen = len;
+
                if (!switch_channel_ready(channel)) {
                        status = SWITCH_STATUS_FALSE;
                        break;
@@ -2348,23 +2341,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
                        continue;
                }
 
+
                flags = SWITCH_SPEECH_FLAG_BLOCKING;
                status = switch_core_speech_read_tts(sh, abuf, &ilen, &flags);
 
                if (status != SWITCH_STATUS_SUCCESS) {
-                       write_frame.datalen = (uint32_t) codec->implementation->decoded_bytes_per_packet;
-                       write_frame.samples = (uint32_t) (write_frame.datalen / 2);
-                       memset(write_frame.data, 0, write_frame.datalen);
-                       for (x = 0; !done && x < lead_in_out; x++) {
-                               switch_yield(codec->implementation->microseconds_per_packet);
-                               if (timer) {
-                                       write_frame.timestamp = timer->samplecount;
-                               }
-                               if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
-                                       done = 1;
-                                       break;
-                               }
-                       }
                        if (status == SWITCH_STATUS_BREAK) {
                                status = SWITCH_STATUS_SUCCESS;
                        }
@@ -2376,7 +2357,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
                }
 
                write_frame.datalen = (uint32_t) ilen;
-               write_frame.samples = (uint32_t) (ilen / 2);
+               write_frame.samples = (uint32_t) (ilen / 2 / sh->channels);
                if (timer) {
                        write_frame.timestamp = timer->samplecount;
                }
@@ -2466,6 +2447,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
        switch_channel_t *channel = switch_core_session_get_channel(session);
        uint32_t rate = 0;
        int interval = 0;
+       uint32_t channels;
        switch_frame_t write_frame = { 0 };
        switch_timer_t ltimer, *timer;
        switch_codec_t lcodec, *codec;
@@ -2519,10 +2501,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
 
        rate = read_impl.actual_samples_per_second;
        interval = read_impl.microseconds_per_packet / 1000;
+       channels = read_impl.number_of_channels;
 
        if (need_create) {
                memset(sh, 0, sizeof(*sh));
-               if ((status = switch_core_speech_open(sh, tts_name, voice_name, (uint32_t) rate, interval, &flags, NULL)) != SWITCH_STATUS_SUCCESS) {
+               if ((status = switch_core_speech_open(sh, tts_name, voice_name, (uint32_t) rate, interval, read_impl.number_of_channels, &flags, NULL)) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid TTS module!\n");
                        switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
                        switch_ivr_clear_speech_cache(session);
@@ -2543,11 +2526,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text(switch_core_session_t *ses
        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "OPEN TTS %s\n", tts_name);
 
        codec_name = "L16";
-
+       
        if (need_create) {
                if (switch_core_codec_init(codec,
                                                                   codec_name,
-                                                                  NULL, (int) rate, interval, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
+                                                                  NULL, (int) rate, interval, channels, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
                                                                   pool) == SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Raw Codec Activated\n");
                } else {
index 36ee0e7796f94531092597e039e2fafb57bee626..d62e5f7337737c07ef001aadd9a56a7da034b938 100644 (file)
@@ -364,6 +364,25 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                 switch_proxy_decode,   /* function to decode encoded data into raw data */
                                                                                 switch_proxy_destroy); /* deinitalize a codec handle using this implementation */
 
+  SWITCH_ADD_CODEC(codec_interface, "PROXY PASS-THROUGH");
+  switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                     0, /* the IANA code number */
+                     "PROXY", /* the IANA code name */
+                     NULL,  /* default fmtp to send (can be overridden by the init function) */
+                     8000,  /* samples transferred per second */
+                     8000,  /* actual samples transferred per second */
+                     0, /* bits transferred per second */
+                     20000, /* number of microseconds per frame */
+                     160, /* number of samples per frame */
+                     320 * 2, /* number of bytes per frame decompressed */
+                     320 * 2, /* number of bytes per frame compressed */
+                     2, /* number of channels represented */
+                     1, /* number of frames per network packet */
+                     switch_proxy_init, /* function to initialize a codec handle using this implementation */
+                     switch_proxy_encode, /* function to encode raw data into encoded data */
+                     switch_proxy_decode, /* function to decode encoded data into raw data */
+                     switch_proxy_destroy); /* deinitalize a codec handle using this implementation */
+
        SWITCH_ADD_CODEC(codec_interface, "RAW Signed Linear (16 bit)");
 
        for (counta = 1; counta <= 3; counta++) {
@@ -377,6 +396,11 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                                 SWITCH_CODEC_TYPE_AUDIO, 70, "L16", NULL, rate, rate, bps,
                                                                                                 mpf * countb, spf * countb, bpf * countb, ebpf * countb, 1, spf * countb,
                                                                                                 switch_raw_init, switch_raw_encode, switch_raw_decode, switch_raw_destroy);
+
+                       switch_core_codec_add_implementation(pool, codec_interface,
+                                                                                                SWITCH_CODEC_TYPE_AUDIO, 70, "L16", NULL, rate, rate, bps,
+                                                                                                mpf * countb, spf * countb, bpf * countb * 2, ebpf * countb, 2, spf * countb,
+                                                                                                switch_raw_init, switch_raw_encode, switch_raw_decode, switch_raw_destroy);
                }
                rate = rate * 2;
                bps = bps * 2;
@@ -408,6 +432,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                         switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                         switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+    switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                       70,  /* the IANA code number */
+                       "L16", /* the IANA code name */
+                       NULL,  /* default fmtp to send (can be overridden by the init function) */
+                       12000, /* samples transferred per second */
+                       12000, /* actual samples transferred per second */
+                       192000 * 2,  /* bits transferred per second */
+                       ms_per_frame,  /* number of microseconds per frame */
+                       samples_per_frame, /* number of samples per frame */
+                       bytes_per_frame * 2, /* number of bytes per frame decompressed */
+                       bytes_per_frame * 2, /* number of bytes per frame compressed */
+                       2, /* number of channels represented */
+                       1, /* number of frames per network packet */
+                       switch_raw_init, /* function to initialize a codec handle using this implementation */
+                       switch_raw_encode, /* function to encode raw data into encoded data */
+                       switch_raw_decode, /* function to decode encoded data into raw data */
+                       switch_raw_destroy); /* deinitalize a codec handle using this implementation */
+
                samples_per_frame += 240;
                bytes_per_frame += 480;
                ms_per_frame += 20000;
@@ -437,6 +479,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                         switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                         switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+    switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                       70,  /* the IANA code number */
+                       "L16", /* the IANA code name */
+                       NULL,  /* default fmtp to send (can be overridden by the init function) */
+                       24000, /* samples transferred per second */
+                       24000, /* actual samples transferred per second */
+                       384000 * 2,  /* bits transferred per second */
+                       ms_per_frame,  /* number of microseconds per frame */
+                       samples_per_frame, /* number of samples per frame */
+                       bytes_per_frame * 2, /* number of bytes per frame decompressed */
+                       bytes_per_frame * 2, /* number of bytes per frame compressed */
+                       2, /* number of channels represented */
+                       1, /* number of frames per network packet */
+                       switch_raw_init, /* function to initialize a codec handle using this implementation */
+                       switch_raw_encode, /* function to encode raw data into encoded data */
+                       switch_raw_decode, /* function to decode encoded data into raw data */
+                       switch_raw_destroy); /* deinitalize a codec handle using this implementation */
+
                samples_per_frame += 480;
                bytes_per_frame += 960;
                ms_per_frame += 20000;
@@ -468,6 +528,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                         switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                         switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+               switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
+                                                                                        70,    /* the IANA code number */
+                                                                                        "L16", /* the IANA code name */
+                                                                                        NULL,  /* default fmtp to send (can be overridden by the init function) */
+                                                                                        48000, /* samples transferred per second */
+                                                                                        48000, /* actual samples transferred per second */
+                                                                                        768000 * 2,    /* bits transferred per second */
+                                                                                        ms_per_frame,  /* number of microseconds per frame */
+                                                                                        samples_per_frame * 2, /* number of samples per frame */
+                                                                                        bytes_per_frame * 2,   /* number of bytes per frame decompressed */
+                                                                                        bytes_per_frame * 2,   /* number of bytes per frame compressed */
+                                                                                        2,     /* number of channels represented */
+                                                                                        1,     /* number of frames per network packet */
+                                                                                        switch_raw_init,       /* function to initialize a codec handle using this implementation */
+                                                                                        switch_raw_encode,     /* function to encode raw data into encoded data */
+                                                                                        switch_raw_decode,     /* function to decode encoded data into raw data */
+                                                                                        switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
+
                samples_per_frame += 96;
                bytes_per_frame += 192;
                ms_per_frame += 2000;
@@ -498,6 +576,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                         switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                         switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+    switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                       70,  /* the IANA code number */
+                       "L16", /* the IANA code name */
+                       NULL,  /* default fmtp to send (can be overridden by the init function) */
+                       8000,  /* samples transferred per second */
+                       8000,  /* actual samples transferred per second */
+                       128000 * 2,  /* bits transferred per second */
+                       ms_per_frame,  /* number of microseconds per frame */
+                       samples_per_frame, /* number of samples per frame */
+                       bytes_per_frame * 2, /* number of bytes per frame decompressed */
+                       bytes_per_frame * 2, /* number of bytes per frame compressed */
+                       2, /* number of channels represented */
+                       1, /* number of frames per network packet */
+                       switch_raw_init, /* function to initialize a codec handle using this implementation */
+                       switch_raw_encode, /* function to encode raw data into encoded data */
+                       switch_raw_decode, /* function to decode encoded data into raw data */
+                       switch_raw_destroy); /* deinitalize a codec handle using this implementation */
+
                samples_per_frame += 16;
                bytes_per_frame += 32;
                ms_per_frame += 2000;
@@ -527,6 +623,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                         switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                         switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+    switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                       70,  /* the IANA code number */
+                       "L16", /* the IANA code name */
+                       NULL,  /* default fmtp to send (can be overridden by the init function) */
+                       16000, /* samples transferred per second */
+                       16000, /* actual samples transferred per second */
+                       256000 * 2,  /* bits transferred per second */
+                       ms_per_frame,  /* number of microseconds per frame */
+                       samples_per_frame, /* number of samples per frame */
+                       bytes_per_frame * 2, /* number of bytes per frame decompressed */
+                       bytes_per_frame * 2, /* number of bytes per frame compressed */
+                       2, /* number of channels represented */
+                       1, /* number of frames per network packet */
+                       switch_raw_init, /* function to initialize a codec handle using this implementation */
+                       switch_raw_encode, /* function to encode raw data into encoded data */
+                       switch_raw_decode, /* function to decode encoded data into raw data */
+                       switch_raw_destroy); /* deinitalize a codec handle using this implementation */
+
                samples_per_frame += 32;
                bytes_per_frame += 64;
                ms_per_frame += 2000;
@@ -557,6 +671,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                         switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                         switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+    switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                       70,  /* the IANA code number */
+                       "L16", /* the IANA code name */
+                       NULL,  /* default fmtp to send (can be overridden by the init function) */
+                       32000, /* samples transferred per second */
+                       32000, /* actual samples transferred per second */
+                       512000 * 2,  /* bits transferred per second */
+                       ms_per_frame,  /* number of microseconds per frame */
+                       samples_per_frame, /* number of samples per frame */
+                       bytes_per_frame * 2, /* number of bytes per frame decompressed */
+                       bytes_per_frame * 2, /* number of bytes per frame compressed */
+                       2, /* number of channels represented */
+                       1, /* number of frames per network packet */
+                       switch_raw_init, /* function to initialize a codec handle using this implementation */
+                       switch_raw_encode, /* function to encode raw data into encoded data */
+                       switch_raw_decode, /* function to decode encoded data into raw data */
+                       switch_raw_destroy); /* deinitalize a codec handle using this implementation */
+
                samples_per_frame += 64;
                bytes_per_frame += 128;
                ms_per_frame += 2000;
@@ -585,6 +717,25 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                         switch_raw_encode,     /* function to encode raw data into encoded data */
                                                                                         switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                         switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
+
+               switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
+                                                                                        70,    /* the IANA code number */
+                                                                                        "L16", /* the IANA code name */
+                                                                                        NULL,  /* default fmtp to send (can be overridden by the init function) */
+                                                                                        48000, /* samples transferred per second */
+                                                                                        48000, /* actual samples transferred per second */
+                                                                                        768000 * 2,    /* bits transferred per second */
+                                                                                        ms_per_frame,  /* number of microseconds per frame */
+                                                                                        samples_per_frame * 2, /* number of samples per frame */
+                                                                                        bytes_per_frame * 2,   /* number of bytes per frame decompressed */
+                                                                                        bytes_per_frame * 2,   /* number of bytes per frame compressed */
+                                                                                        2,     /* number of channels represented */
+                                                                                        1,     /* number of frames per network packet */
+                                                                                        switch_raw_init,       /* function to initialize a codec handle using this implementation */
+                                                                                        switch_raw_encode,     /* function to encode raw data into encoded data */
+                                                                                        switch_raw_decode,     /* function to decode encoded data into raw data */
+                                                                                        switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
+
                samples_per_frame += 480;
                bytes_per_frame += 960;
                ms_per_frame += 10000;
@@ -608,6 +759,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                 switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                 switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+  switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                     70,  /* the IANA code number */
+                     "L16", /* the IANA code name */
+                     NULL,  /* default fmtp to send (can be overridden by the init function) */
+                     22050, /* samples transferred per second */
+                     22050, /* actual samples transferred per second */
+                     352800 * 2,  /* bits transferred per second */
+                     20000, /* number of microseconds per frame */
+                     441, /* number of samples per frame */
+                     882 * 2, /* number of bytes per frame decompressed */
+                     882 * 2, /* number of bytes per frame compressed */
+                     2, /* number of channels represented */
+                     1, /* number of frames per network packet */
+                     switch_raw_init, /* function to initialize a codec handle using this implementation */
+                     switch_raw_encode, /* function to encode raw data into encoded data */
+                     switch_raw_decode, /* function to decode encoded data into raw data */
+                     switch_raw_destroy); /* deinitalize a codec handle using this implementation */
+
        switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
                                                                                 70,    /* the IANA code number */
                                                                                 "L16", /* the IANA code name */
@@ -626,6 +795,24 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                 switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                 switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
+  switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                     70,  /* the IANA code number */
+                     "L16", /* the IANA code name */
+                     NULL,  /* default fmtp to send (can be overridden by the init function) */
+                     11025, /* samples transferred per second */
+                     11025, /* actual samples transferred per second */
+                     176400 * 2,  /* bits transferred per second */
+                     40000, /* number of microseconds per frame */
+                     441, /* number of samples per frame */
+                     882 * 2, /* number of bytes per frame decompressed */
+                     882 * 2, /* number of bytes per frame compressed */
+                     2, /* number of channels represented */
+                     1, /* number of frames per network packet */
+                     switch_raw_init, /* function to initialize a codec handle using this implementation */
+                     switch_raw_encode, /* function to encode raw data into encoded data */
+                     switch_raw_decode, /* function to decode encoded data into raw data */
+                     switch_raw_destroy); /* deinitalize a codec handle using this implementation */
+
 
        switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
                                                                                 70,    /* the IANA code number */
@@ -645,7 +832,23 @@ SWITCH_MODULE_LOAD_FUNCTION(core_pcm_load)
                                                                                 switch_raw_decode,     /* function to decode encoded data into raw data */
                                                                                 switch_raw_destroy);   /* deinitalize a codec handle using this implementation */
 
-
+  switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,  /* enumeration defining the type of the codec */
+                     70,  /* the IANA code number */
+                     "L16", /* the IANA code name */
+                     NULL,  /* default fmtp to send (can be overridden by the init function) */
+                     11025, /* samples transferred per second */
+                     11025, /* actual samples transferred per second */
+                     176400 * 2,  /* bits transferred per second */
+                     32000, /* number of microseconds per frame */
+                     256, /* number of samples per frame */
+                     512 * 2, /* number of bytes per frame decompressed */
+                     512 * 2, /* number of bytes per frame compressed */
+                     2, /* number of channels represented */
+                     1, /* number of frames per network packet */
+                     switch_raw_init, /* function to initialize a codec handle using this implementation */
+                     switch_raw_encode, /* function to encode raw data into encoded data */
+                     switch_raw_decode, /* function to decode encoded data into raw data */
+                     switch_raw_destroy); /* deinitalize a codec handle using this implementation */
 
        /* indicate that the module should continue to be loaded */
 
index 2363ace9c839b15263dd7e2fc8b9d847ebfd5608..a0b7249763052c156b54d771474ea1cf6480a6c7 100644 (file)
@@ -78,7 +78,8 @@ SWITCH_DECLARE(switch_status_t) switch_resample_perform_create(switch_audio_resa
        resampler->factor = (lto_rate / lfrom_rate);
        resampler->rfactor = (lfrom_rate / lto_rate);
        resampler->to_size = resample_buffer(to_rate, from_rate, (uint32_t) to_size);
-       resampler->to = malloc(resampler->to_size * sizeof(int16_t));
+       resampler->to = malloc(resampler->to_size * sizeof(int16_t) * channels);
+       resampler->channels = channels;
 
        return SWITCH_STATUS_SUCCESS;
 }
@@ -271,18 +272,55 @@ SWITCH_DECLARE(uint32_t) switch_unmerge_sln(int16_t *data, uint32_t samples, int
        return x;
 }
 
-SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t channels)
+SWITCH_DECLARE(void) switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels)
 {
        switch_size_t i = 0;
        uint32_t j = 0;
 
-       for (i = 0; i < samples; i++) {
-               int32_t z = 0;
-               for (j = 0; j < channels; j++) {
-                       z += data[i * channels + j];
-                       switch_normalize_to_16bit(z);
-                       data[i] = (int16_t) z;
+       switch_assert(channels < 11);
+
+       if (orig_channels > channels) {
+               for (i = 0; i < samples; i++) {
+                       int32_t z = 0;
+                       for (j = 0; j < orig_channels; j++) {
+                               z += data[i * orig_channels + j];
+                               switch_normalize_to_16bit(z);
+                               data[i] = (int16_t) z;
+                       }
+               }
+       } else if (orig_channels < channels) {
+
+               /* interesting problem... take a give buffer and double up every sample in the buffer without using any other buffer.....
+                  This way beats the other i think bacause there is no malloc but I do have to copy the data twice */
+#if 1
+               uint32_t k = 0, len = samples * orig_channels;
+
+               for (i = 0; i < len; i++) {
+                       data[i+len] = data[i];
+               }
+
+               for (i = 0; i < samples; i++) {
+                       for (j = 0; j < channels; j++) { 
+                               data[k++] = data[i + samples];
+                       }
                }
+
+#else 
+               uint32_t k = 0, len = samples * 2 * orig_channels;
+               int16_t *orig = NULL;
+
+               switch_zmalloc(orig, len);
+               memcpy(orig, data, len);
+
+               for (i = 0; i < samples; i++) {
+                       for (j = 0; j < channels; j++) { 
+                               data[k++] = orig[i];
+                       }
+               }
+               
+               free(orig);
+#endif
+
        }
 }