129 #define M_PI 3.14159265358979323846
131 #define MAX_FRAME_LENGTH 256
141 float in_fifo[MAX_FRAME_LENGTH];
142 float out_fifo[MAX_FRAME_LENGTH];
143 float fft_worksp[2*MAX_FRAME_LENGTH];
144 float last_phase[MAX_FRAME_LENGTH/2+1];
145 float sum_phase[MAX_FRAME_LENGTH/2+1];
146 float output_accum[2*MAX_FRAME_LENGTH];
147 float ana_freq[MAX_FRAME_LENGTH];
148 float ana_magn[MAX_FRAME_LENGTH];
149 float syn_freq[MAX_FRAME_LENGTH];
150 float sys_magn[MAX_FRAME_LENGTH];
162 static void smb_fft(
float *fft_buffer,
long fft_frame_size,
long sign);
163 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);
175 .
type =
"pitchshift",
196 shift = datastore->
data;
199 pitch_shift(f, shift->tx.shift_amount, &shift->tx);
201 pitch_shift(f, shift->rx.shift_amount, &shift->rx);
207 static int pitchshift_helper(
struct ast_channel *chan,
const char *cmd,
char *data,
const char *value)
215 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
219 ast_channel_lock(chan);
221 ast_channel_unlock(chan);
223 if (!(datastore = ast_datastore_alloc(&pitchshift_datastore, NULL))) {
226 if (!(shift =
ast_calloc(1,
sizeof(*shift)))) {
233 datastore->
data = shift;
236 ast_channel_unlock(chan);
237 shift = datastore->
data;
241 if (!strcasecmp(value,
"highest")) {
243 }
else if (!strcasecmp(value,
"higher")) {
245 }
else if (!strcasecmp(value,
"high")) {
247 }
else if (!strcasecmp(value,
"lowest")) {
249 }
else if (!strcasecmp(value,
"lower")) {
251 }
else if (!strcasecmp(value,
"low")) {
254 if (!sscanf(value,
"%30f", &amount) || (amount <= 0) || (amount > 4)) {
259 if (!strcasecmp(data,
"rx")) {
260 shift->rx.shift_amount = amount;
261 }
else if (!strcasecmp(data,
"tx")) {
262 shift->tx.shift_amount = amount;
263 }
else if (!strcasecmp(data,
"both")) {
264 shift->rx.shift_amount = amount;
265 shift->tx.shift_amount = amount;
271 ast_channel_lock(chan);
273 ast_channel_unlock(chan);
281 ast_log(LOG_ERROR,
"Invalid argument provided to the %s function\n", cmd);
288 static void smb_fft(
float *fft_buffer,
long fft_frame_size,
long sign)
290 float wr, wi, arg, *p1, *p2, temp;
291 float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i;
292 long i, bitm, j, le, le2, k;
294 for (i = 2; i < 2 * fft_frame_size - 2; i += 2) {
295 for (bitm = 2, j = 0; bitm < 2 * fft_frame_size; bitm <<= 1) {
302 p1 = fft_buffer + i; p2 = fft_buffer + j;
303 temp = *p1; *(p1++) = *p2;
304 *(p2++) = temp; temp = *p1;
305 *p1 = *p2; *p2 = temp;
308 for (k = 0, le = 2; k < (long) (log(fft_frame_size) / log(2.) + .5); k++) {
313 arg = M_PI / (le2>>1);
315 wi = sign * sin(arg);
316 for (j = 0; j < le2; j += 2) {
317 p1r = fft_buffer+j; p1i = p1r + 1;
318 p2r = p1r + le2; p2i = p2r + 1;
319 for (i = j; i < 2 * fft_frame_size; i += le) {
320 tr = *p2r * ur - *p2i * ui;
321 ti = *p2r * ui + *p2i * ur;
322 *p2r = *p1r - tr; *p2i = *p1i - ti;
323 *p1r += tr; *p1i += ti;
324 p1r += le; p1i += le;
325 p2r += le; p2i += le;
327 tr = ur * wr - ui * wi;
328 ui = ur * wi + ui * wr;
334 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)
336 float *in_fifo = fft_data->in_fifo;
337 float *out_fifo = fft_data->out_fifo;
338 float *fft_worksp = fft_data->fft_worksp;
339 float *last_phase = fft_data->last_phase;
340 float *sum_phase = fft_data->sum_phase;
341 float *output_accum = fft_data->output_accum;
342 float *ana_freq = fft_data->ana_freq;
343 float *ana_magn = fft_data->ana_magn;
344 float *syn_freq = fft_data->syn_freq;
345 float *sys_magn = fft_data->sys_magn;
347 double magn, phase, tmp, window, real, imag;
348 double freq_per_bin, expect;
349 long i,k, qpd, index, in_fifo_latency, step_size, fft_frame_size2;
352 fft_frame_size2 = fft_frame_size / 2;
353 step_size = fft_frame_size / osamp;
354 freq_per_bin = sample_rate / (double) fft_frame_size;
355 expect = 2. * M_PI * (double) step_size / (
double) fft_frame_size;
356 in_fifo_latency = fft_frame_size-step_size;
358 if (fft_data->gRover == 0) {
359 fft_data->gRover = in_fifo_latency;
363 for (i = 0; i < num_samps_to_process; i++){
366 in_fifo[fft_data->gRover] = indata[i];
367 outdata[i] = out_fifo[fft_data->gRover - in_fifo_latency];
371 if (fft_data->gRover >= fft_frame_size) {
372 fft_data->gRover = in_fifo_latency;
375 for (k = 0; k < fft_frame_size;k++) {
376 window = -.5 * cos(2. * M_PI * (
double) k / (
double) fft_frame_size) + .5;
377 fft_worksp[2*k] = in_fifo[k] * window;
378 fft_worksp[2*k+1] = 0.;
383 smb_fft(fft_worksp, fft_frame_size, -1);
386 for (k = 0; k <= fft_frame_size2; k++) {
389 real = fft_worksp[2*k];
390 imag = fft_worksp[2*k+1];
393 magn = 2. * sqrt(real * real + imag * imag);
394 phase = atan2(imag, real);
397 tmp = phase - last_phase[k];
398 last_phase[k] = phase;
401 tmp -= (double) k * expect;
410 tmp -= M_PI * (double) qpd;
413 tmp = osamp * tmp / (2. * M_PI);
416 tmp = (double) k * freq_per_bin + tmp * freq_per_bin;
426 memset(sys_magn, 0, fft_frame_size *
sizeof(
float));
427 memset(syn_freq, 0, fft_frame_size *
sizeof(
float));
428 for (k = 0; k <= fft_frame_size2; k++) {
429 index = k * pitchShift;
430 if (index <= fft_frame_size2) {
431 sys_magn[index] += ana_magn[k];
432 syn_freq[index] = ana_freq[k] * pitchShift;
438 for (k = 0; k <= fft_frame_size2; k++) {
445 tmp -= (double) k * freq_per_bin;
451 tmp = 2. * M_PI * tmp / osamp;
454 tmp += (double) k * expect;
458 phase = sum_phase[k];
461 fft_worksp[2*k] = magn * cos(phase);
462 fft_worksp[2*k+1] = magn * sin(phase);
466 for (k = fft_frame_size + 2; k < 2 * fft_frame_size; k++) {
471 smb_fft(fft_worksp, fft_frame_size, 1);
474 for (k = 0; k < fft_frame_size; k++) {
475 window = -.5 * cos(2. * M_PI * (
double) k / (
double) fft_frame_size) + .5;
476 output_accum[k] += 2. * window * fft_worksp[2*k] / (fft_frame_size2 * osamp);
478 for (k = 0; k < step_size; k++) {
479 out_fifo[k] = output_accum[k];
483 memmove(output_accum, output_accum+step_size, fft_frame_size *
sizeof(
float));
486 for (k = 0; k < in_fifo_latency; k++) {
487 in_fifo[k] = in_fifo[k+step_size];
493 static int pitch_shift(
struct ast_frame *f,
float amount,
struct fft_data *fft)
495 int16_t *fun = (int16_t *) f->
data.ptr;
499 if (!amount || amount == 1 || !fun || (f->
samples % 32)) {
502 for (samples = 0; samples < f->
samples; samples += 32) {
510 .
name =
"PITCH_SHIFT",
511 .write = pitchshift_helper,
514 static int unload_module(
void)
519 static int load_module(
void)
525 AST_MODULE_INFO_STANDARD_EXTENDED(
ASTERISK_GPL_KEY,
"Audio Effects Dialplan Functions");
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
Structure for a data store type.
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Structure for a data store object.
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.
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
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.
struct ast_frame_subclass subclass
ast_audiohook_manipulate_callback manipulate_callback
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
General Asterisk PBX channel definitions.
Data structure associated with a custom dialplan function.
Core PBX routines and definitions.
static void destroy_callback(void *data)
Helper function used by datastores to destroy the speech structure upon hangup.
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
Module has failed to load, may be in an inconsistent state.
Data structure associated with a single frame of data.
enum ast_audiohook_status status
struct ast_format * format
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define ast_custom_function_register(acf)
Register a custom function.