mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-06-07 13:35:00 +00:00
sample platter
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6706 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
2ff5e3ec40
commit
44636d333f
@ -40,6 +40,7 @@
|
|||||||
#define SWITCH_MODULE_INTERFACES_H
|
#define SWITCH_MODULE_INTERFACES_H
|
||||||
|
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
#include "switch_resample.h"
|
||||||
|
|
||||||
SWITCH_BEGIN_EXTERN_C
|
SWITCH_BEGIN_EXTERN_C
|
||||||
/*! \brief A table of functions to execute at various states
|
/*! \brief A table of functions to execute at various states
|
||||||
@ -262,6 +263,8 @@ struct switch_file_handle {
|
|||||||
unsigned int samples;
|
unsigned int samples;
|
||||||
/*! the current samplerate */
|
/*! the current samplerate */
|
||||||
uint32_t samplerate;
|
uint32_t samplerate;
|
||||||
|
/*! the current native samplerate */
|
||||||
|
uint32_t native_rate;
|
||||||
/*! the number of channels */
|
/*! the number of channels */
|
||||||
uint8_t channels;
|
uint8_t channels;
|
||||||
/*! integer representation of the format */
|
/*! integer representation of the format */
|
||||||
@ -289,6 +292,10 @@ struct switch_file_handle {
|
|||||||
uint32_t offset_pos;
|
uint32_t offset_pos;
|
||||||
uint32_t last_pos;
|
uint32_t last_pos;
|
||||||
int32_t vol;
|
int32_t vol;
|
||||||
|
switch_audio_resampler_t *resampler;
|
||||||
|
switch_buffer_t *buffer;
|
||||||
|
switch_byte_t *dbuf;
|
||||||
|
switch_size_t dbuflen;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! \brief Abstract interface to an asr module */
|
/*! \brief Abstract interface to an asr module */
|
||||||
|
@ -91,7 +91,7 @@ SWITCH_DECLARE(switch_status_t) switch_resample_create(switch_audio_resampler_t
|
|||||||
\brief Destroy an existing resampler handle
|
\brief Destroy an existing resampler handle
|
||||||
\param resampler the resampler handle to destroy
|
\param resampler the resampler handle to destroy
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(void) switch_resample_destroy(switch_audio_resampler_t *resampler);
|
SWITCH_DECLARE(void) switch_resample_destroy(switch_audio_resampler_t **resampler);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Resample one float buffer into another using specifications of a given handle
|
\brief Resample one float buffer into another using specifications of a given handle
|
||||||
|
@ -1465,6 +1465,9 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t * thread,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch_resample_destroy(&member->read_resampler);
|
||||||
|
switch_resample_destroy(&member->mux_resampler);
|
||||||
|
|
||||||
switch_clear_flag_locked(member, MFLAG_ITHREAD);
|
switch_clear_flag_locked(member, MFLAG_ITHREAD);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1239,6 +1239,8 @@ SWITCH_STANDARD_APP(record_function)
|
|||||||
int argc;
|
int argc;
|
||||||
char *mydata, *argv[4] = { 0 };
|
char *mydata, *argv[4] = { 0 };
|
||||||
char *l = NULL;
|
char *l = NULL;
|
||||||
|
const char *tmp;
|
||||||
|
int rate;
|
||||||
|
|
||||||
channel = switch_core_session_get_channel(session);
|
channel = switch_core_session_get_channel(session);
|
||||||
assert(channel != NULL);
|
assert(channel != NULL);
|
||||||
@ -1280,6 +1282,13 @@ SWITCH_STANDARD_APP(record_function)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((tmp = switch_channel_get_variable(channel, "record_rate"))) {
|
||||||
|
rate = atoi(tmp);
|
||||||
|
if (rate > 0) {
|
||||||
|
fh.samplerate = rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
args.input_callback = on_dtmf;
|
args.input_callback = on_dtmf;
|
||||||
status = switch_ivr_record_file(session, &fh, path, &args, limit);
|
status = switch_ivr_record_file(session, &fh, path, &args, limit);
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||||||
local_stream_context_t *cp;
|
local_stream_context_t *cp;
|
||||||
char file_buf[128] = "", path_buf[512] = "";
|
char file_buf[128] = "", path_buf[512] = "";
|
||||||
switch_timer_t timer = {0};
|
switch_timer_t timer = {0};
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
if (switch_core_timer_init(&timer, source->timer_name, source->interval, source->samples, source->pool) != SWITCH_STATUS_SUCCESS) {
|
if (switch_core_timer_init(&timer, source->timer_name, source->interval, source->samples, source->pool) != SWITCH_STATUS_SUCCESS) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
|
||||||
@ -98,27 +98,37 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "open directory: %s\n", source->location);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "open directory: %s\n", source->location);
|
||||||
switch_yield(1000000);
|
switch_yield(1000000);
|
||||||
|
|
||||||
while(RUNNING && (fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) {
|
while(RUNNING) {
|
||||||
switch_size_t olen;
|
switch_size_t olen;
|
||||||
uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
|
uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
|
||||||
|
|
||||||
snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname);
|
if (fd > -1) {
|
||||||
if (switch_stristr(".loc", path_buf)) {
|
|
||||||
int fd, bytes;
|
|
||||||
char *p;
|
char *p;
|
||||||
|
if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
|
||||||
if ((fd = open(path_buf, O_RDONLY)) < 0) {
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
|
|
||||||
switch_yield(1000000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes = read(fd, path_buf, sizeof(path_buf));
|
|
||||||
if ((p = strchr(path_buf, '\r')) ||
|
if ((p = strchr(path_buf, '\r')) ||
|
||||||
(p = strchr(path_buf, '\n'))) {
|
(p = strchr(path_buf, '\n'))) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!(fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname);
|
||||||
|
|
||||||
|
if (switch_stristr(".loc", path_buf)) {
|
||||||
|
if ((fd = open(path_buf, O_RDONLY)) < 0) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
|
||||||
|
switch_yield(1000000);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fname = path_buf;
|
fname = path_buf;
|
||||||
@ -139,6 +149,7 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||||||
while (RUNNING) {
|
while (RUNNING) {
|
||||||
switch_core_timer_next(&timer);
|
switch_core_timer_next(&timer);
|
||||||
olen = source->samples;
|
olen = source->samples;
|
||||||
|
|
||||||
if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
|
if (switch_core_file_read(&fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
|
||||||
switch_core_file_close(&fh);
|
switch_core_file_close(&fh);
|
||||||
break;
|
break;
|
||||||
@ -156,9 +167,14 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch_dir_close(source->dir_handle);
|
switch_dir_close(source->dir_handle);
|
||||||
|
source->dir_handle = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fd > -1) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
switch_core_destroy_memory_pool(&source->pool);
|
switch_core_destroy_memory_pool(&source->pool);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -168,25 +184,37 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
|
|||||||
{
|
{
|
||||||
local_stream_context_t *context;
|
local_stream_context_t *context;
|
||||||
local_stream_source_t *source;
|
local_stream_source_t *source;
|
||||||
|
char *alt_path = NULL;
|
||||||
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
|
||||||
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
|
if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing!\n");
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alt_path = switch_mprintf("%s/%d", path, handle->samplerate);
|
||||||
|
|
||||||
switch_mutex_lock(globals.mutex);
|
switch_mutex_lock(globals.mutex);
|
||||||
|
if ((source = switch_core_hash_find(globals.source_hash, alt_path))) {
|
||||||
|
path = alt_path;
|
||||||
|
} else {
|
||||||
source = switch_core_hash_find(globals.source_hash, path);
|
source = switch_core_hash_find(globals.source_hash, path);
|
||||||
|
}
|
||||||
switch_mutex_unlock(globals.mutex);
|
switch_mutex_unlock(globals.mutex);
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unknown source %s\n", path);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unknown source %s\n", path);
|
||||||
return SWITCH_STATUS_FALSE;
|
status = SWITCH_STATUS_FALSE;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
|
if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
|
||||||
return SWITCH_STATUS_MEMERR;
|
status = SWITCH_STATUS_MEMERR;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
handle->samples = 0;
|
handle->samples = 0;
|
||||||
handle->samplerate = source->rate;
|
handle->samplerate = source->rate;
|
||||||
handle->channels = source->channels;
|
handle->channels = source->channels;
|
||||||
@ -201,7 +229,8 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
|
|||||||
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
|
switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
|
||||||
if (switch_buffer_create_dynamic(&context->audio_buffer, 512, 1024, 0) != SWITCH_STATUS_SUCCESS) {
|
if (switch_buffer_create_dynamic(&context->audio_buffer, 512, 1024, 0) != SWITCH_STATUS_SUCCESS) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
|
||||||
return SWITCH_STATUS_MEMERR;
|
status = SWITCH_STATUS_MEMERR;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
context->source = source;
|
context->source = source;
|
||||||
@ -211,8 +240,9 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
|
|||||||
source->context_list = context;
|
source->context_list = context;
|
||||||
switch_mutex_unlock(source->mutex);
|
switch_mutex_unlock(source->mutex);
|
||||||
|
|
||||||
|
end:
|
||||||
return SWITCH_STATUS_SUCCESS;
|
switch_safe_free(alt_path);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static switch_status_t local_stream_file_close(switch_file_handle_t *handle)
|
static switch_status_t local_stream_file_close(switch_file_handle_t *handle)
|
||||||
@ -350,6 +380,7 @@ static void launch_threads(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
source->samples = switch_bytes_per_frame(source->rate, source->interval);
|
source->samples = switch_bytes_per_frame(source->rate, source->interval);
|
||||||
|
|
||||||
switch_core_hash_insert(globals.source_hash, source->name, source);
|
switch_core_hash_insert(globals.source_hash, source->name, source);
|
||||||
|
|
||||||
switch_mutex_init(&source->mutex, SWITCH_MUTEX_NESTED, source->pool);
|
switch_mutex_init(&source->mutex, SWITCH_MUTEX_NESTED, source->pool);
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* Anthony Minessale II <anthmct@yahoo.com>
|
* Anthony Minessale II <anthmct@yahoo.com>
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* mod_native_file.c -- Framework Demo Module
|
* mod_native_file.c -- Native Files
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
@ -61,6 +61,9 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||||||
int mode = 0;
|
int mode = 0;
|
||||||
char *ext;
|
char *ext;
|
||||||
struct format_map *map = NULL;
|
struct format_map *map = NULL;
|
||||||
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||||
|
char *alt_path = NULL, *next, *last, *ldup = NULL;
|
||||||
|
size_t alt_len = 0;
|
||||||
|
|
||||||
if ((ext = strrchr(path, '.')) == 0) {
|
if ((ext = strrchr(path, '.')) == 0) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n");
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Format\n");
|
||||||
@ -141,11 +144,28 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||||||
if ((mode & SFM_WRITE) && sf_format_check(&context->sfinfo) == 0) {
|
if ((mode & SFM_WRITE) && sf_format_check(&context->sfinfo) == 0) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error : file format is invalid (0x%08X).\n", context->sfinfo.format);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error : file format is invalid (0x%08X).\n", context->sfinfo.format);
|
||||||
return SWITCH_STATUS_GENERR;
|
return SWITCH_STATUS_GENERR;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
alt_len = strlen(path) + 10;
|
||||||
|
switch_zmalloc(alt_path, alt_len);
|
||||||
|
|
||||||
|
switch_copy_string(alt_path, path, alt_len);
|
||||||
|
if ((last = strrchr(alt_path, *SWITCH_PATH_SEPARATOR))) {
|
||||||
|
next = ++last;
|
||||||
|
ldup = strdup(last);
|
||||||
|
switch_assert(ldup);
|
||||||
|
switch_snprintf(next, alt_len - (last - alt_path), "%d%s%s", handle->samplerate, SWITCH_PATH_SEPARATOR, ldup);
|
||||||
|
if ((context->handle = sf_open(alt_path, mode, &context->sfinfo))) {
|
||||||
|
path = alt_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context->handle) {
|
||||||
if ((context->handle = sf_open(path, mode, &context->sfinfo)) == 0) {
|
if ((context->handle = sf_open(path, mode, &context->sfinfo)) == 0) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening File [%s] [%s]\n", path, sf_strerror(context->handle));
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening File [%s] [%s]\n", path, sf_strerror(context->handle));
|
||||||
return SWITCH_STATUS_GENERR;
|
status = SWITCH_STATUS_GENERR;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opening File [%s] %dhz\n", path, context->sfinfo.samplerate);
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opening File [%s] %dhz\n", path, context->sfinfo.samplerate);
|
||||||
@ -158,7 +178,14 @@ static switch_status_t sndfile_file_open(switch_file_handle_t *handle, const cha
|
|||||||
handle->speed = 0;
|
handle->speed = 0;
|
||||||
handle->private_info = context;
|
handle->private_info = context;
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
switch_safe_free(alt_path);
|
||||||
|
switch_safe_free(ldup);
|
||||||
|
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static switch_status_t sndfile_file_close(switch_file_handle_t *handle)
|
static switch_status_t sndfile_file_close(switch_file_handle_t *handle)
|
||||||
|
@ -73,10 +73,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_open(switch_file_handle_t *fh,
|
|||||||
fh->handler = switch_core_strdup(fh->memory_pool, rhs);
|
fh->handler = switch_core_strdup(fh->memory_pool, rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rate) {
|
if (!fh->samplerate) {
|
||||||
fh->samplerate = rate;
|
if (!(fh->samplerate = rate)) {
|
||||||
} else {
|
fh->samplerate = 8000;
|
||||||
rate = 8000;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channels) {
|
if (channels) {
|
||||||
@ -85,26 +85,131 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_open(switch_file_handle_t *fh,
|
|||||||
fh->channels = 1;
|
fh->channels = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((status = fh->file_interface->file_open(fh, file_path)) == SWITCH_STATUS_SUCCESS) {
|
if ((status = fh->file_interface->file_open(fh, file_path)) != SWITCH_STATUS_SUCCESS) {
|
||||||
switch_set_flag(fh, SWITCH_FILE_OPEN);
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((flags & SWITCH_FILE_FLAG_READ)) {
|
||||||
|
fh->native_rate = fh->samplerate;
|
||||||
|
} else {
|
||||||
|
fh->native_rate = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fh->samplerate != rate) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Sample rate doesn't match\n");
|
||||||
|
if ((flags & SWITCH_FILE_FLAG_READ)) {
|
||||||
|
fh->samplerate = rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_set_flag(fh, SWITCH_FILE_OPEN);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh, void *data, switch_size_t *len)
|
SWITCH_DECLARE(switch_status_t) switch_core_file_read(switch_file_handle_t *fh, void *data, switch_size_t *len)
|
||||||
{
|
{
|
||||||
|
switch_status_t status;
|
||||||
|
switch_size_t orig_len = *len;
|
||||||
|
|
||||||
switch_assert(fh != NULL);
|
switch_assert(fh != NULL);
|
||||||
switch_assert(fh->file_interface != NULL);
|
switch_assert(fh->file_interface != NULL);
|
||||||
|
|
||||||
return fh->file_interface->file_read(fh, data, len);
|
if (fh->buffer && switch_buffer_inuse(fh->buffer)) {
|
||||||
|
*len = switch_buffer_read(fh->buffer, data, orig_len);
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status = fh->file_interface->file_read(fh, data, len)) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
orig_len * 10,
|
||||||
|
fh->samplerate,
|
||||||
|
orig_len * 10,
|
||||||
|
fh->memory_pool) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
|
||||||
|
return SWITCH_STATUS_GENERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fh->resampler->from_len = switch_short_to_float(data, fh->resampler->from, (int) *len);
|
||||||
|
fh->resampler->to_len =
|
||||||
|
switch_resample_process(fh->resampler, fh->resampler->from, fh->resampler->from_len, fh->resampler->to, fh->resampler->to_size, 0);
|
||||||
|
|
||||||
|
if (fh->resampler->to_len > orig_len) {
|
||||||
|
if (!fh->buffer) {
|
||||||
|
switch_buffer_create_dynamic(&fh->buffer, fh->resampler->to_len * 2, fh->resampler->to_len * 4, fh->resampler->to_len * 8);
|
||||||
|
switch_assert(fh->buffer);
|
||||||
|
}
|
||||||
|
if (!fh->dbuf) {
|
||||||
|
fh->dbuflen = fh->resampler->to_len * 2;
|
||||||
|
fh->dbuf = switch_core_alloc(fh->memory_pool, fh->dbuflen);
|
||||||
|
}
|
||||||
|
switch_assert(fh->resampler->to_len <= fh->dbuflen);
|
||||||
|
|
||||||
|
switch_float_to_short(fh->resampler->to, (int16_t *) fh->dbuf, fh->resampler->to_len);
|
||||||
|
switch_buffer_write(fh->buffer, fh->dbuf, fh->resampler->to_len * 2);
|
||||||
|
*len = switch_buffer_read(fh->buffer, data, orig_len);
|
||||||
|
} else {
|
||||||
|
switch_float_to_short(fh->resampler->to, data, fh->resampler->to_len);
|
||||||
|
*len = fh->resampler->to_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, void *data, switch_size_t *len)
|
SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, void *data, switch_size_t *len)
|
||||||
{
|
{
|
||||||
|
switch_size_t orig_len = *len;
|
||||||
|
|
||||||
switch_assert(fh != NULL);
|
switch_assert(fh != NULL);
|
||||||
switch_assert(fh->file_interface != NULL);
|
switch_assert(fh->file_interface != NULL);
|
||||||
|
|
||||||
|
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,
|
||||||
|
orig_len * 10,
|
||||||
|
fh->samplerate,
|
||||||
|
orig_len * 10,
|
||||||
|
fh->memory_pool) != SWITCH_STATUS_SUCCESS) {
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
|
||||||
|
return SWITCH_STATUS_GENERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fh->resampler->from_len = switch_short_to_float(data, fh->resampler->from, (int) *len);
|
||||||
|
fh->resampler->to_len =
|
||||||
|
switch_resample_process(fh->resampler, fh->resampler->from, fh->resampler->from_len, fh->resampler->to, fh->resampler->to_size, 0);
|
||||||
|
if (fh->resampler->to_len > orig_len) {
|
||||||
|
if (!fh->dbuf) {
|
||||||
|
fh->dbuflen = fh->resampler->to_len * 2;
|
||||||
|
fh->dbuf = switch_core_alloc(fh->memory_pool, fh->dbuflen);
|
||||||
|
}
|
||||||
|
switch_assert(fh->resampler->to_len <= fh->dbuflen);
|
||||||
|
switch_float_to_short(fh->resampler->to, (int16_t *) fh->dbuf, fh->resampler->to_len);
|
||||||
|
data = fh->dbuf;
|
||||||
|
} else {
|
||||||
|
switch_float_to_short(fh->resampler->to, data, fh->resampler->to_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = fh->resampler->to_len;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*len) {
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
return fh->file_interface->file_write(fh, data, len);
|
return fh->file_interface->file_write(fh, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +256,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh)
|
|||||||
switch_clear_flag(fh, SWITCH_FILE_OPEN);
|
switch_clear_flag(fh, SWITCH_FILE_OPEN);
|
||||||
status = fh->file_interface->file_close(fh);
|
status = fh->file_interface->file_close(fh);
|
||||||
|
|
||||||
|
if (fh->buffer) {
|
||||||
|
switch_buffer_destroy(&fh->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch_resample_destroy(&fh->resampler);
|
||||||
|
|
||||||
|
|
||||||
if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) {
|
if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) {
|
||||||
switch_core_destroy_memory_pool(&fh->memory_pool);
|
switch_core_destroy_memory_pool(&fh->memory_pool);
|
||||||
}
|
}
|
||||||
|
@ -566,11 +566,9 @@ SWITCH_DECLARE(void) switch_core_session_reset(switch_core_session_t *session)
|
|||||||
char buf[256];
|
char buf[256];
|
||||||
switch_size_t has;
|
switch_size_t has;
|
||||||
|
|
||||||
/* sweep theese under the rug, they wont be leaked they will be reclaimed
|
/* clear resamplers*/
|
||||||
when the session ends.
|
switch_resample_destroy(&session->read_resampler);
|
||||||
*/
|
switch_resample_destroy(&session->write_resampler);
|
||||||
session->read_resampler = NULL;
|
|
||||||
session->write_resampler = NULL;
|
|
||||||
|
|
||||||
/* clear indications */
|
/* clear indications */
|
||||||
switch_core_session_flush_message(session);
|
switch_core_session_flush_message(session);
|
||||||
|
@ -348,8 +348,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
|
|||||||
const char *vval;
|
const char *vval;
|
||||||
time_t start = 0;
|
time_t start = 0;
|
||||||
uint32_t org_silence_hits = 0;
|
uint32_t org_silence_hits = 0;
|
||||||
switch_audio_resampler_t *resampler = NULL;
|
|
||||||
int16_t resamp_out[2048];
|
|
||||||
|
|
||||||
if (!fh) {
|
if (!fh) {
|
||||||
fh = &lfh;
|
fh = &lfh;
|
||||||
@ -362,27 +360,13 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
|
|||||||
switch_assert(read_codec != NULL);
|
switch_assert(read_codec != NULL);
|
||||||
|
|
||||||
fh->channels = read_codec->implementation->number_of_channels;
|
fh->channels = read_codec->implementation->number_of_channels;
|
||||||
|
fh->native_rate = read_codec->implementation->actual_samples_per_second;
|
||||||
|
|
||||||
if (fh->samplerate) {
|
|
||||||
if (fh->samplerate != read_codec->implementation->actual_samples_per_second) {
|
|
||||||
if (switch_resample_create(&resampler,
|
|
||||||
read_codec->implementation->actual_samples_per_second,
|
|
||||||
read_codec->implementation->actual_samples_per_second * 20,
|
|
||||||
fh->samplerate,
|
|
||||||
fh->samplerate * 20,
|
|
||||||
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
|
|
||||||
return SWITCH_STATUS_GENERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fh->samplerate = read_codec->implementation->actual_samples_per_second;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switch_core_file_open(fh,
|
if (switch_core_file_open(fh,
|
||||||
file,
|
file,
|
||||||
fh->channels,
|
fh->channels,
|
||||||
fh->samplerate,
|
read_codec->implementation->actual_samples_per_second,
|
||||||
SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
||||||
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
|
||||||
switch_core_session_reset(session);
|
switch_core_session_reset(session);
|
||||||
@ -553,18 +537,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!switch_test_flag(fh, SWITCH_FILE_PAUSE)) {
|
if (!switch_test_flag(fh, SWITCH_FILE_PAUSE) && !switch_test_flag(read_frame, SFF_CNG)) {
|
||||||
int16_t *data = read_frame->data;
|
int16_t *data = read_frame->data;
|
||||||
len = (switch_size_t) read_frame->datalen / 2;
|
len = (switch_size_t) read_frame->datalen / 2;
|
||||||
|
|
||||||
if (resampler) {
|
|
||||||
resampler->from_len = switch_short_to_float(read_frame->data, resampler->from, (int) len);
|
|
||||||
resampler->to_len = switch_resample_process(resampler, resampler->from, resampler->from_len, resampler->to, resampler->to_size, 0);
|
|
||||||
switch_float_to_short(resampler->to, resamp_out, read_frame->datalen);
|
|
||||||
len = resampler->to_len;
|
|
||||||
data = resamp_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switch_core_file_write(fh, data, &len) != SWITCH_STATUS_SUCCESS) {
|
if (switch_core_file_write(fh, data, &len) != SWITCH_STATUS_SUCCESS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -111,11 +111,17 @@ SWITCH_DECLARE(uint32_t) switch_resample_process(switch_audio_resampler_t *resam
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_resample_destroy(switch_audio_resampler_t *resampler)
|
SWITCH_DECLARE(void) switch_resample_destroy(switch_audio_resampler_t **resampler)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (resampler && *resampler) {
|
||||||
#ifndef DISABLE_RESAMPLE
|
#ifndef DISABLE_RESAMPLE
|
||||||
resample_close(resampler->resampler);
|
if ((*resampler)->resampler) {
|
||||||
|
resample_close((*resampler)->resampler);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
*resampler = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user