69 #include "asterisk/module.h"
116 #define M_PI 3.14159265358979323846
118 #define MAX_FRAME_LENGTH 256
149 static void smb_fft(
float *fft_buffer,
long fft_frame_size,
long sign);
150 static void smb_pitch_shift(
float pitchShift,
long num_samps_to_process,
long fft_frame_size,
long osamp,
float sample_rate, int16_t *indata, int16_t *outdata,
struct fft_data *
fft_data);
162 .
type =
"pitchshift",
186 shift = datastore->
data;
216 if (!(shift =
ast_calloc(1,
sizeof(*shift)))) {
223 datastore->
data = shift;
227 shift = datastore->
data;
231 if (!strcasecmp(value,
"highest")) {
233 }
else if (!strcasecmp(value,
"higher")) {
235 }
else if (!strcasecmp(value,
"high")) {
237 }
else if (!strcasecmp(value,
"lowest")) {
239 }
else if (!strcasecmp(value,
"lower")) {
241 }
else if (!strcasecmp(value,
"low")) {
244 if (!sscanf(value,
"%30f", &amount) || (amount <= 0) || (amount > 4)) {
249 if (!strcasecmp(data,
"rx")) {
251 }
else if (!strcasecmp(data,
"tx")) {
253 }
else if (!strcasecmp(data,
"both")) {
278 static void smb_fft(
float *fft_buffer,
long fft_frame_size,
long sign)
280 float wr, wi, arg, *p1, *p2, temp;
281 float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i;
282 long i, bitm, j, le, le2, k;
284 for (i = 2; i < 2 * fft_frame_size - 2; i += 2) {
285 for (bitm = 2, j = 0; bitm < 2 * fft_frame_size; bitm <<= 1) {
292 p1 = fft_buffer + i; p2 = fft_buffer + j;
293 temp = *p1; *(p1++) = *p2;
294 *(p2++) = temp; temp = *p1;
295 *p1 = *p2; *p2 = temp;
298 for (k = 0, le = 2; k < (long) (log(fft_frame_size) / log(2.) + .5); k++) {
303 arg =
M_PI / (le2>>1);
305 wi = sign * sin(arg);
306 for (j = 0; j < le2; j += 2) {
307 p1r = fft_buffer+j; p1i = p1r + 1;
308 p2r = p1r + le2; p2i = p2r + 1;
309 for (i = j; i < 2 * fft_frame_size; i += le) {
310 tr = *p2r * ur - *p2i * ui;
311 ti = *p2r * ui + *p2i * ur;
312 *p2r = *p1r - tr; *p2i = *p1i - ti;
313 *p1r += tr; *p1i += ti;
314 p1r += le; p1i += le;
315 p2r += le; p2i += le;
317 tr = ur * wr - ui * wi;
318 ui = ur * wi + ui * wr;
324 static void smb_pitch_shift(
float pitchShift,
long num_samps_to_process,
long fft_frame_size,
long osamp,
float sample_rate, int16_t *indata, int16_t *outdata,
struct fft_data *
fft_data)
326 float *in_fifo = fft_data->
in_fifo;
327 float *out_fifo = fft_data->
out_fifo;
332 float *ana_freq = fft_data->
ana_freq;
333 float *ana_magn = fft_data->
ana_magn;
334 float *syn_freq = fft_data->
syn_freq;
335 float *sys_magn = fft_data->
sys_magn;
337 double magn, phase, tmp, window, real, imag;
338 double freq_per_bin, expct;
339 long i,k, qpd, index, in_fifo_latency,
step_size, fft_frame_size2;
342 fft_frame_size2 = fft_frame_size / 2;
343 step_size = fft_frame_size / osamp;
344 freq_per_bin = sample_rate / (double) fft_frame_size;
345 expct = 2. *
M_PI * (double) step_size / (
double) fft_frame_size;
346 in_fifo_latency = fft_frame_size-
step_size;
348 if (fft_data->
gRover == 0) {
349 fft_data->
gRover = in_fifo_latency;
353 for (i = 0; i < num_samps_to_process; i++){
356 in_fifo[fft_data->
gRover] = indata[i];
357 outdata[i] = out_fifo[fft_data->
gRover - in_fifo_latency];
361 if (fft_data->
gRover >= fft_frame_size) {
362 fft_data->
gRover = in_fifo_latency;
365 for (k = 0; k < fft_frame_size;k++) {
366 window = -.5 *
cos(2. *
M_PI * (
double) k / (
double) fft_frame_size) + .5;
367 fft_worksp[2*k] = in_fifo[k] * window;
368 fft_worksp[2*k+1] = 0.;
373 smb_fft(fft_worksp, fft_frame_size, -1);
376 for (k = 0; k <= fft_frame_size2; k++) {
379 real = fft_worksp[2*k];
380 imag = fft_worksp[2*k+1];
383 magn = 2. * sqrt(real * real + imag * imag);
384 phase = atan2(imag, real);
387 tmp = phase - last_phase[k];
388 last_phase[k] = phase;
391 tmp -= (double) k * expct;
400 tmp -=
M_PI * (double) qpd;
403 tmp = osamp * tmp / (2. *
M_PI);
406 tmp = (double) k * freq_per_bin + tmp * freq_per_bin;
416 memset(sys_magn, 0, fft_frame_size *
sizeof(
float));
417 memset(syn_freq, 0, fft_frame_size *
sizeof(
float));
418 for (k = 0; k <= fft_frame_size2; k++) {
419 index = k * pitchShift;
420 if (index <= fft_frame_size2) {
421 sys_magn[index] += ana_magn[k];
422 syn_freq[index] = ana_freq[k] * pitchShift;
428 for (k = 0; k <= fft_frame_size2; k++) {
435 tmp -= (double) k * freq_per_bin;
441 tmp = 2. *
M_PI * tmp / osamp;
444 tmp += (double) k * expct;
448 phase = sum_phase[k];
451 fft_worksp[2*k] = magn *
cos(phase);
452 fft_worksp[2*k+1] = magn * sin(phase);
456 for (k = fft_frame_size + 2; k < 2 * fft_frame_size; k++) {
461 smb_fft(fft_worksp, fft_frame_size, 1);
464 for (k = 0; k < fft_frame_size; k++) {
465 window = -.5 *
cos(2. *
M_PI * (
double) k / (
double) fft_frame_size) + .5;
466 output_accum[k] += 2. * window * fft_worksp[2*k] / (fft_frame_size2 * osamp);
469 out_fifo[k] = output_accum[k];
473 memmove(output_accum, output_accum+step_size, fft_frame_size *
sizeof(
float));
476 for (k = 0; k < in_fifo_latency; k++) {
485 int16_t *fun = (int16_t *) f->
data.
ptr;
489 if (!amount || amount == 1 || !fun || (f->
samples % 32)) {
492 for (samples = 0; samples < f->
samples; samples += 32) {
500 .
name =
"PITCH_SHIFT",
union ast_frame_subclass subclass
#define ast_channel_lock(chan)
Main Channel structure associated with a channel.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Asterisk main include file. File version handling, generic pbx functions.
struct ast_audiohook audiohook
float out_fifo[MAX_FRAME_LENGTH]
float ana_magn[MAX_FRAME_LENGTH]
float output_accum[2 *MAX_FRAME_LENGTH]
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source)
Initialize an audiohook structure.
static int pitchshift_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value)
float ana_freq[MAX_FRAME_LENGTH]
Structure for a data store type.
static int step_size(struct g726_state *state_ptr)
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
static int pitchshift_cb(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *f, enum ast_audiohook_direction direction)
static force_inline int ast_format_rate(format_t format)
Get the sample rate for a given format.
Structure for a data store object.
float sum_phase[MAX_FRAME_LENGTH/2+1]
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
float in_fifo[MAX_FRAME_LENGTH]
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
static void smb_pitch_shift(float pitchShift, long num_samps_to_process, long fft_frame_size, long osamp, float sample_rate, int16_t *indata, int16_t *outdata, struct fft_data *fft_data)
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
ast_audiohook_manipulate_callback manipulate_callback
float fft_worksp[2 *MAX_FRAME_LENGTH]
General Asterisk PBX channel definitions.
Data structure associated with a custom dialplan function.
float syn_freq[MAX_FRAME_LENGTH]
static void destroy_callback(void *data)
static struct ast_custom_function pitch_shift_function
#define AST_FORMAT_SLINEAR16
Core PBX routines and definitions.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
static int unload_module(void)
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
static int load_module(void)
#define ast_channel_unlock(chan)
float sys_magn[MAX_FRAME_LENGTH]
if(yyss+yystacksize-1<=yyssp)
static int pitch_shift(struct ast_frame *f, float amount, struct fft_data *fft_data)
static struct ast_datastore_info pitchshift_datastore
#define AST_FORMAT_SLINEAR
Data structure associated with a single frame of data.
enum ast_audiohook_status status
enum ast_frame_type frametype
float last_phase[MAX_FRAME_LENGTH/2+1]
#define ASTERISK_GPL_KEY
The text the key() function should return.
union ast_frame::@172 data
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
static void smb_fft(float *fft_buffer, long fft_frame_size, long sign)
#define ast_custom_function_register(acf)
Register a custom function.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.