--- src/audio/Makefile.am | 1 + src/audio/tone.c | 576 +++++++++++++++++++++++++++++++++++ src/audio/tone.h | 54 ++++ src/include/reef/audio/component.h | 2 + src/include/reef/math/trig.h | 44 +++ src/include/reef/trace.h | 1 + src/include/uapi/ipc.h | 8 + src/math/trig.c | 595 +++++++++++++++++++++++++++++++++++++ src/tasks/audio.c | 1 + 9 files changed, 1282 insertions(+) create mode 100644 src/audio/tone.c create mode 100644 src/audio/tone.h create mode 100644 src/include/reef/math/trig.h create mode 100644 src/math/trig.c
diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am index 235e785..6f0381a 100644 --- a/src/audio/Makefile.am +++ b/src/audio/Makefile.am @@ -1,6 +1,7 @@ noinst_LIBRARIES = libaudio.a
libaudio_a_SOURCES = \ + tone.c \ src.c \ src_core.c \ mixer.c \ diff --git a/src/audio/tone.c b/src/audio/tone.c new file mode 100644 index 0000000..f305c03 --- /dev/null +++ b/src/audio/tone.c @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2016, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com + * Liam Girdwood liam.r.girdwood@linux.intel.com + * Keyon Jie yang.jie@linux.intel.com + */ + +#include <stdint.h> +#include <stddef.h> +#include <errno.h> +#include <reef/reef.h> +#include <reef/lock.h> +#include <reef/list.h> +#include <reef/stream.h> +#include <reef/alloc.h> +#include <reef/work.h> +#include <reef/clock.h> +#include <reef/audio/component.h> +#include <reef/audio/format.h> +#include <reef/audio/pipeline.h> +#include <reef/math/trig.h> +#include "tone.h" + +#ifdef MODULE_TEST +#include <stdio.h> +#endif + +#define trace_tone(__e) trace_event(TRACE_CLASS_TONE, __e) +#define tracev_tone(__e) tracev_event(TRACE_CLASS_TONE, __e) +#define trace_tone_error(__e) trace_error(TRACE_CLASS_TONE, __e) + +#define TONE_NUM_FS 13 /* Table size for 8-192 kHz range */ +#define TONE_AMPLITUDE_DEFAULT 2147484 /* -60 dB from full scale */ +#define TONE_FREQUENCY_DEFAULT 16334848 /* 997 in Q18.14 */ + +static int32_t tonegen(struct tone_state *sg); +static void tonegen_control(struct tone_state *sg); +static void tonegen_update_f(struct tone_state *sg, int32_t f); + + +/* 2*pi/Fs lookup tables in Q1.31 for each Fs */ +static const int32_t tone_fs_list[TONE_NUM_FS] = { + 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, + 64000, 88200, 96000, 176400, 192000 +}; +static const int32_t tone_pi2_div_fs[TONE_NUM_FS] = { + 1686630, 1223858, 843315, 611929, 562210, 421657, 305965, + 281105, 210829, 152982, 140552, 76491, 70276 +}; + +/* tone component private data */ + +/* TODO: Remove *source when internal endpoint is possible */ +struct comp_data { + struct tone_state sg; + void (*tone_func)(struct comp_dev *dev, struct comp_buffer *sink, + struct comp_buffer *source, uint32_t frames); + +}; + +/* + * Tone generator algorithm code + */ + +static void tone_s32_default(struct comp_dev *dev, struct comp_buffer *sink, + struct comp_buffer *source, uint32_t frames) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int32_t sine_sample; + int32_t *dest = (int32_t*) sink->w_ptr; + int i, n, n_wrap_dest; + int nch = sink->params.pcm->channels; + + n = frames * nch; + while (n > 0) { + n_wrap_dest = (int32_t *) sink->end_addr - dest; + if (n < n_wrap_dest) { + /* No circular wrap need */ + while (n > 0) { + /* Update period count for sweeps, etc. */ + tonegen_control(&cd->sg); + /* Calculate mono sine wave sample and then + * duplicate to channels. + */ + sine_sample = tonegen(&cd->sg); + n -= nch; + for (i = 0; i < nch; i++) { + *dest = sine_sample; + dest++; + } + } + } else { + /* Process until wrap */ + while (n_wrap_dest > 0) { + tonegen_control(&cd->sg); + sine_sample = tonegen(&cd->sg); + n -= nch; + n_wrap_dest -= nch; + for (i = 0; i < nch; i++) { + *dest = sine_sample; + dest++; + } + } + /* No need to check if past end_addr, + * it is so just subtract buffer size. + */ + dest = (int32_t *) ((size_t) dest - sink->alloc_size); + } + } + sink->w_ptr = dest; + comp_update_sink_free_avail(sink, frames * nch); +} + +static int32_t tonegen(struct tone_state *sg) +{ + int64_t sine, w; + + /* sg->w is angle in Q4.28 radians format, sin() returns Q1.31 */ + /* sg->a is amplitude as Q1.31 */ + sine = q_mults_32x32(sin_fixed(sg->w), sg->a, 31, 31, 31); + + /* Next point */ + w = (int64_t) sg->w + sg->w_step; + sg->w = (w > PI_MUL2_Q4_28) + ? (int32_t) (w - PI_MUL2_Q4_28) : (int32_t) w; + + if (sg->mute) + return 0; + else + return(int32_t) sine; /* Q1.31 no saturation need */ +} + +static void tonegen_control(struct tone_state *sg) +{ + int64_t a, p; + + /* Count samples, 125 us blocks */ + sg->sample_count++; + if (sg->sample_count < sg->samples_in_block) + return; + + sg->sample_count = 0; + if (sg->block_count < INT32_MAXVALUE) + sg->block_count++; + + /* Fadein ramp during tone */ + if (sg->block_count < sg->tone_length) { + if (sg->a == 0) + sg->w = 0; /* Reset phase to have less clicky ramp */ + + if (sg->a > sg->a_target) { + a = (int64_t) sg->a - sg->ramp_step; + if (a < sg->a_target) + a = sg->a_target; + + } else { + a = (int64_t) sg->a + sg->ramp_step; + if (a > sg->a_target) + a = sg->a_target; + } + sg->a = (int32_t) a; + } + + /* Fadeout ramp after tone*/ + if (sg->block_count > sg->tone_length) { + a = (int64_t) sg->a - sg->ramp_step; + if (a < 0) + a = 0; + + sg->a = (int32_t) a; + } + + /* New repeated tone, update for frequency or amplitude sweep */ + if ((sg->block_count > sg->tone_period) + && (sg->repeat_count + 1 < sg->repeats)) { + sg->block_count = 0; + if (sg->ampl_coef > 0) { + sg->a_target = sat_int32(q_multsr_32x32( + sg->a_target, + sg->ampl_coef, 31, 30, 31)); + sg->a = (sg->ramp_step > sg->a_target) + ? sg->a_target : sg->ramp_step; + } + if (sg->freq_coef > 0) { + /* f is Q16.16, freq_coef is Q2.30 */ + p = q_multsr_32x32(sg->f, sg->freq_coef, 16, 30, 16); + tonegen_update_f(sg, (int32_t) p); /* No saturation */ + } + sg->repeat_count++; + } +} + +static inline void tonegen_set_a(struct tone_state *sg, int32_t a) +{ + sg->a_target = a; +} + +static inline void tonegen_set_f(struct tone_state *sg, int32_t f) +{ + sg->f = f; +} + +/* Tone sweep parameters description: + * fc - Multiplication factor for frequency as Q2.30 for logarithmic change + * ac - Multiplication factor for amplitude as Q2.30 for logarithmic change + * l - Tone length in samples, this is the active length of tone + * p - Tone period in samples, this is the length including the pause after beep + * r - Repeated number of beeps + */ + +static void tonegen_set_sweep(struct tone_state *sg, int32_t fc, int32_t ac, + uint32_t l, uint32_t p, uint32_t r) +{ + sg->repeats = r; + + /* Zeros as defaults make a nicer API without need to remember + * the neutral settings for sweep and repeat parameters. + */ + sg->freq_coef = (fc > 0) ? fc : ONE_Q2_30; /* Set freq mult to 1.0 */ + sg->ampl_coef = (ac > 0) ? ac : ONE_Q2_30; /* Set ampl mult to 1.0 */ + sg->tone_length = (l > 0) ? l : INT32_MAXVALUE; /* Count rate 125 us */ + sg->tone_period = (p > 0) ? p : INT32_MAXVALUE; /* Count rate 125 us */ +} + +/* Tone ramp parameters: + * step - Value that is added or subtracted to amplitude. A zero or negative + * number disables the ramp and amplitude is immediately modified to + * final value. + */ + +static inline void tonegen_set_linramp(struct tone_state *sg, int32_t step) +{ + sg->ramp_step = (step > 0) ? step : INT32_MAXVALUE; +} + +static inline int32_t tonegen_get_f(struct tone_state *sg) +{ + return sg->f; +} + +static inline int32_t tonegen_get_a(struct tone_state *sg) +{ + return sg->a_target; +} + +static inline void tonegen_mute(struct tone_state *sg) +{ + sg->mute = 1; +} + +static inline void tonegen_unmute(struct tone_state *sg) +{ + sg->mute = 0; +} + +static void tonegen_update_f(struct tone_state *sg, int32_t f) +{ + int64_t w_tmp; + int64_t f_max; + + /* Calculate Fs/2, fs is Q32.0, f is Q16.16 */ + f_max = Q_SHIFT_LEFT((int64_t) sg->fs, 0, 16 - 1); + f_max = (f_max > INT32_MAXVALUE) ? INT32_MAXVALUE : f_max; + sg->f = (f > f_max) ? f_max : f; + w_tmp = q_multsr_32x32(sg->f, sg->c, 16, 31, 28); /* Q16 x Q31 -> Q28 */ + w_tmp = (w_tmp > PI_Q4_28) ? PI_Q4_28 : w_tmp; /* Limit to pi Q4.28 */ + sg->w_step = (int32_t) w_tmp; + +#ifdef MODULE_TEST + printf("Fs=%d, f_max=%d, f_new=%.3f\n", + sg->fs, (int32_t) (f_max >> 16), sg->f / 65536.0); +#endif +} + +static void tonegen_reset(struct tone_state *sg) +{ + sg->mute = 1; + sg->a = 0; + sg->a_target = TONE_AMPLITUDE_DEFAULT; + sg->c = 0; + sg->f = TONE_FREQUENCY_DEFAULT; + sg->w = 0; + sg->w_step = 0; + + sg->block_count = 0; + sg->repeat_count = 0; + sg->repeats = 0; + sg->sample_count = 0; + sg->samples_in_block = 0; + + /* Continuous tone */ + sg->freq_coef = ONE_Q2_30; /* Set freq multiplier to 1.0 */ + sg->ampl_coef = ONE_Q2_30; /* Set ampl multiplier to 1.0 */ + sg->tone_length = INT32_MAXVALUE; + sg->tone_period = INT32_MAXVALUE; + sg->ramp_step = ONE_Q1_31; /* Set lin ramp modification to max */ +} + +static int tonegen_init(struct tone_state *sg, int32_t fs, int32_t f, int32_t a) +{ + int idx, i; + + sg->a_target = a; + sg->a = (sg->ramp_step > sg->a_target) ? sg->a_target : sg->ramp_step; + + idx = -1; + sg->mute = 1; + sg->fs = 0; + + /* Find index of current sample rate and then get from lookup table the + * corresponding 2*pi/Fs value. + */ + for (i = 0; i < TONE_NUM_FS; i++) { + if (fs == tone_fs_list[i]) + idx = i; + } + + if (idx < 0) { + sg->w_step = 0; + return -EINVAL; + } + + sg->fs = fs; + sg->c = tone_pi2_div_fs[idx]; /* Store 2*pi/Fs */ + sg->mute = 0; + tonegen_update_f(sg, f); + + /* 125us as Q1.31 is 268435, calculate fs * 125e-6 in Q31.0 */ + sg->samples_in_block = (int32_t) q_multsr_32x32(fs, 268435, 0, 31, 0); + + return 0; +} + +/* + * End of algorithm code. Next the standard component methods. + */ + +static struct comp_dev *tone_new(struct sof_ipc_comp *comp) +{ + struct comp_dev *dev; + struct comp_data *cd; + + trace_tone("TNw"); + dev = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*dev)); + if (dev == NULL) + return NULL; + + //memcpy(&dev->comp, comp, sizeof(struct sof_ipc_comp_tone)); + + + cd = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd)); + if (cd == NULL) { + rfree(dev); + return NULL; + } + + comp_set_drvdata(dev, cd); + + + tonegen_reset(&cd->sg); + + return dev; +} + +static void tone_free(struct comp_dev *dev) +{ + struct tone_data *td = comp_get_drvdata(dev); + + trace_tone("TFr"); + + rfree(td); + rfree(dev); +} + +/* set component audio stream parameters */ +static int tone_params(struct comp_dev *dev, struct stream_params *params) +{ + trace_tone("TPa"); + + /* Tone generator supports only S32_LE PCM format */ + if ((params->type != STREAM_TYPE_PCM) + || (params->pcm->frame_fmt != SOF_IPC_FRAME_S32_LE)) + return -EINVAL; + + /* Don't do any data transformation */ + comp_set_sink_params(dev, params); + + return 0; +} + +/* used to pass standard and bespoke commands (with data) to component */ +static int tone_cmd(struct comp_dev *dev, int cmd, void *data) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct sof_ipc_comp_tone *cv; + trace_tone("TCm"); + + switch (cmd) { + case COMP_CMD_TONE: + trace_tone("Tto"); + cv = (struct sof_ipc_comp_tone *) data; + /* Ignore channels while tone implementation is mono */ + tonegen_set_f(&cd->sg, cv->frequency); + tonegen_set_a(&cd->sg, cv->amplitude); + tonegen_set_sweep(&cd->sg, cv->freq_mult, cv->ampl_mult, + cv->length, cv->period, cv->repeats); + tonegen_set_linramp(&cd->sg, cv->ramp_step); + break; + case COMP_CMD_VOLUME: + trace_tone("TVo"); + break; + case COMP_CMD_MUTE: + trace_tone("TMu"); + tonegen_mute(&cd->sg); + break; + case COMP_CMD_UNMUTE: + trace_tone("TUm"); + tonegen_unmute(&cd->sg); + break; + case COMP_CMD_START: + trace_tone("TSt"); + dev->state = COMP_STATE_RUNNING; + break; + case COMP_CMD_STOP: + trace_tone("TSp"); + if (dev->state == COMP_STATE_RUNNING || + dev->state == COMP_STATE_DRAINING || + dev->state == COMP_STATE_PAUSED) { + comp_buffer_reset(dev); + dev->state = COMP_STATE_SETUP; + } + break; + case COMP_CMD_PAUSE: + trace_tone("TPe"); + /* only support pausing for running */ + if (dev->state == COMP_STATE_RUNNING) + dev->state = COMP_STATE_PAUSED; + + break; + case COMP_CMD_RELEASE: + trace_tone("TRl"); + dev->state = COMP_STATE_RUNNING; + break; + default: + trace_tone("TDf"); + + break; + } + + return 0; +} + +/* copy and process stream data from source to sink buffers */ +static int tone_copy(struct comp_dev *dev) +{ + int need_sink; + struct comp_buffer *sink; + struct comp_buffer *source = NULL; + struct comp_data *cd = comp_get_drvdata(dev); + uint32_t cframes; + + trace_comp("Ton"); + + /* tone component sink buffer */ + sink = list_first_item(&dev->bsink_list, struct comp_buffer, + source_list); + cframes = sink->params.pcm->period_count; + + /* Test that sink has enough free frames. Then run once to maintain + * low latency and steady load for tones. + */ + need_sink = cframes * sink->params.pcm->frame_size; + if (sink->free >= need_sink) { + + /* create tone */ + cd->tone_func(dev, sink, source, cframes); + } + + return 0; +} + +static int tone_prepare(struct comp_dev *dev) +{ + int32_t f, a; + struct comp_buffer *sink; + struct comp_data *cd = comp_get_drvdata(dev); + + trace_tone("TPp"); + + sink = list_first_item(&dev->bsink_list, struct comp_buffer, + source_list); + trace_value(sink->params.pcm->channels); + trace_value(sink->params.pcm->rate); + + cd->tone_func = tone_s32_default; + f = tonegen_get_f(&cd->sg); + a = tonegen_get_a(&cd->sg); + if (tonegen_init(&cd->sg, sink->params.pcm->rate, f, a) < 0) + return -EINVAL; + + //dev->preload = PLAT_INT_PERIODS; + dev->state = COMP_STATE_PREPARE; + + return 0; +} + +static int tone_preload(struct comp_dev *dev) +{ + //int i; + trace_tone("TPl"); + + //for (i = 0; i < dev->preload; i++) + // tone_copy(dev); + + return 0; +} + +static int tone_reset(struct comp_dev *dev) +{ + + struct comp_data *cd = comp_get_drvdata(dev); + + trace_tone("TRe"); + + /* Initialize with the defaults */ + tonegen_reset(&cd->sg); + + dev->state = COMP_STATE_INIT; + + return 0; +} + +struct comp_driver comp_tone = { + .type = SOF_COMP_TONE, + .ops = + { + .new = tone_new, + .free = tone_free, + .params = tone_params, + .cmd = tone_cmd, + .copy = tone_copy, + .prepare = tone_prepare, + .reset = tone_reset, + .preload = tone_preload, + }, +}; + +void sys_comp_tone_init(void) +{ + comp_register(&comp_tone); +} diff --git a/src/audio/tone.h b/src/audio/tone.h new file mode 100644 index 0000000..37830db --- /dev/null +++ b/src/audio/tone.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com + * Liam Girdwood liam.r.girdwood@linux.intel.com + * Keyon Jie yang.jie@linux.intel.com + */ + + +struct tone_state { + int mute; + int32_t a; /* Current amplitude Q1.31 */ + int32_t a_target; /* Target amplitude Q1.31 */ + int32_t ampl_coef; /* Amplitude multiplier Q2.30 */ + int32_t c; /* Coefficient 2*pi/Fs Q1.31 */ + int32_t f; /* Frequency Q18.14 */ + int32_t freq_coef; /* Frequency multiplier Q2.30 */ + int32_t fs; /* Sample rate in Hertz Q32.0 */ + int32_t ramp_step; /* Amplitude ramp step Q1.31 */ + int32_t w; /* Angle radians Q4.28 */ + int32_t w_step; /* Angle step Q4.28 */ + uint32_t block_count; + uint32_t repeat_count; + uint32_t repeats; /* Number of repeats for tone (sweep steps) */ + uint32_t sample_count; + uint32_t samples_in_block; /* Samples in 125 us block */ + uint32_t tone_length; /* Active length in 125 us blocks */ + uint32_t tone_period; /* Active + idle time in 125 us blocks */ +}; + diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h index a37aa51..e4f4f8f 100644 --- a/src/include/reef/audio/component.h +++ b/src/include/reef/audio/component.h @@ -75,6 +75,7 @@ #define COMP_CMD_SRC 104 #define COMP_CMD_LOOPBACK 105
+#define COMP_CMD_TONE 106 /* Tone generator amplitude and frequency */
/* MMAP IPC status */ #define COMP_CMD_IPC_MMAP_RPOS 200 /* host read position */ @@ -259,6 +260,7 @@ void sys_comp_mux_init(void); void sys_comp_switch_init(void); void sys_comp_volume_init(void); void sys_comp_src_init(void); +void sys_comp_tone_init(void);
diff --git a/src/include/reef/math/trig.h b/src/include/reef/math/trig.h new file mode 100644 index 0000000..b75f229 --- /dev/null +++ b/src/include/reef/math/trig.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com + * Liam Girdwood liam.r.girdwood@linux.intel.com + * Keyon Jie yang.jie@linux.intel.com + */ + +#ifndef TRIG_H +#define TRIG_H + +#define PI_DIV2_Q4_28 421657428 +#define PI_Q4_28 843314857 +#define PI_MUL2_Q4_28 1686629713 + +int32_t sin_fixed(int32_t w); /* Input is Q4.28, output is Q1.31 */ + +#endif + + diff --git a/src/include/reef/trace.h b/src/include/reef/trace.h index eb3fdd2..04b8d5d 100644 --- a/src/include/reef/trace.h +++ b/src/include/reef/trace.h @@ -83,6 +83,7 @@ #define TRACE_CLASS_SWITCH (15 << 24) #define TRACE_CLASS_MUX (16 << 24) #define TRACE_CLASS_SRC (17 << 24) +#define TRACE_CLASS_TONE (18 << 24)
/* move to config.h */ #define TRACE 1 diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index fc5a88b..7b0fd96 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -505,6 +505,14 @@ struct sof_ipc_comp_mux { struct sof_ipc_comp_tone { struct sof_ipc_comp comp; struct sof_ipc_pcm_comp pcm; + int32_t frequency; + int32_t amplitude; + int32_t freq_mult; + int32_t ampl_mult; + int32_t length; + int32_t period; + int32_t repeats; + int32_t ramp_step; } __attribute__((packed));
/* frees components, buffers and pipelines diff --git a/src/math/trig.c b/src/math/trig.c new file mode 100644 index 0000000..a58e1f4 --- /dev/null +++ b/src/math/trig.c @@ -0,0 +1,595 @@ +/* + * Copyright (c) 2016, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Intel Corporation nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Author: Seppo Ingalsuo seppo.ingalsuo@linux.intel.com + * Liam Girdwood liam.r.girdwood@linux.intel.com + * Keyon Jie yang.jie@linux.intel.com + */ + +#include <stdint.h> +#include <reef/audio/format.h> + + +#define SINE_C_Q20 341782638 /* 2*SINE_NQUART/pi in Q12.20 */ +#define SINE_NQUART 512 /* Must be 2^N */ +#define SINE_TABLE_SIZE (SINE_NQUART+1) + +/* An 1/4 period of sine wave as Q1.31 */ +const int32_t sine_table[SINE_TABLE_SIZE] = { + 0, + 6588387, + 13176712, + 19764913, + 26352928, + 32940695, + 39528151, + 46115236, + 52701887, + 59288042, + 65873638, + 72458615, + 79042909, + 85626460, + 92209205, + 98791081, + 105372028, + 111951983, + 118530885, + 125108670, + 131685278, + 138260647, + 144834714, + 151407418, + 157978697, + 164548489, + 171116732, + 177683365, + 184248325, + 190811551, + 197372981, + 203932553, + 210490206, + 217045877, + 223599506, + 230151030, + 236700388, + 243247517, + 249792358, + 256334847, + 262874923, + 269412525, + 275947592, + 282480061, + 289009871, + 295536961, + 302061269, + 308582734, + 315101294, + 321616889, + 328129457, + 334638936, + 341145265, + 347648383, + 354148229, + 360644742, + 367137860, + 373627523, + 380113669, + 386596237, + 393075166, + 399550396, + 406021864, + 412489512, + 418953276, + 425413098, + 431868915, + 438320667, + 444768293, + 451211734, + 457650927, + 464085813, + 470516330, + 476942419, + 483364019, + 489781069, + 496193509, + 502601279, + 509004318, + 515402566, + 521795963, + 528184448, + 534567963, + 540946445, + 547319836, + 553688076, + 560051103, + 566408860, + 572761285, + 579108319, + 585449903, + 591785976, + 598116478, + 604441351, + 610760535, + 617073970, + 623381597, + 629683357, + 635979190, + 642269036, + 648552837, + 654830534, + 661102068, + 667367379, + 673626408, + 679879097, + 686125386, + 692365218, + 698598533, + 704825272, + 711045377, + 717258790, + 723465451, + 729665303, + 735858287, + 742044345, + 748223418, + 754395449, + 760560379, + 766718151, + 772868706, + 779011986, + 785147934, + 791276492, + 797397602, + 803511207, + 809617248, + 815715670, + 821806413, + 827889421, + 833964637, + 840032003, + 846091463, + 852142959, + 858186434, + 864221832, + 870249095, + 876268167, + 882278991, + 888281511, + 894275670, + 900261412, + 906238681, + 912207419, + 918167571, + 924119082, + 930061894, + 935995952, + 941921200, + 947837582, + 953745043, + 959643527, + 965532978, + 971413341, + 977284561, + 983146583, + 988999351, + 994842809, + 1000676905, + 1006501581, + 1012316784, + 1018122458, + 1023918549, + 1029705003, + 1035481765, + 1041248781, + 1047005996, + 1052753356, + 1058490807, + 1064218296, + 1069935767, + 1075643168, + 1081340445, + 1087027543, + 1092704410, + 1098370992, + 1104027236, + 1109673088, + 1115308496, + 1120933406, + 1126547765, + 1132151521, + 1137744620, + 1143327011, + 1148898640, + 1154459455, + 1160009404, + 1165548435, + 1171076495, + 1176593532, + 1182099495, + 1187594332, + 1193077990, + 1198550419, + 1204011566, + 1209461381, + 1214899812, + 1220326808, + 1225742318, + 1231146290, + 1236538675, + 1241919421, + 1247288477, + 1252645793, + 1257991319, + 1263325005, + 1268646799, + 1273956652, + 1279254515, + 1284540337, + 1289814068, + 1295075658, + 1300325059, + 1305562221, + 1310787095, + 1315999631, + 1321199780, + 1326387493, + 1331562722, + 1336725418, + 1341875532, + 1347013016, + 1352137822, + 1357249900, + 1362349204, + 1367435684, + 1372509294, + 1377569985, + 1382617710, + 1387652421, + 1392674071, + 1397682613, + 1402677999, + 1407660183, + 1412629117, + 1417584755, + 1422527050, + 1427455956, + 1432371426, + 1437273414, + 1442161874, + 1447036759, + 1451898025, + 1456745625, + 1461579513, + 1466399644, + 1471205973, + 1475998455, + 1480777044, + 1485541695, + 1490292364, + 1495029005, + 1499751575, + 1504460029, + 1509154322, + 1513834410, + 1518500249, + 1523151796, + 1527789006, + 1532411836, + 1537020243, + 1541614182, + 1546193612, + 1550758488, + 1555308767, + 1559844407, + 1564365366, + 1568871600, + 1573363067, + 1577839726, + 1582301533, + 1586748446, + 1591180425, + 1595597427, + 1599999410, + 1604386334, + 1608758157, + 1613114837, + 1617456334, + 1621782607, + 1626093615, + 1630389318, + 1634669675, + 1638934646, + 1643184190, + 1647418268, + 1651636840, + 1655839867, + 1660027308, + 1664199124, + 1668355276, + 1672495724, + 1676620431, + 1680729357, + 1684822463, + 1688899710, + 1692961061, + 1697006478, + 1701035921, + 1705049354, + 1709046738, + 1713028036, + 1716993211, + 1720942224, + 1724875039, + 1728791619, + 1732691927, + 1736575926, + 1740443580, + 1744294852, + 1748129706, + 1751948106, + 1755750016, + 1759535401, + 1763304223, + 1767056449, + 1770792043, + 1774510970, + 1778213194, + 1781898680, + 1785567395, + 1789219304, + 1792854372, + 1796472564, + 1800073848, + 1803658188, + 1807225552, + 1810775906, + 1814309215, + 1817825448, + 1821324571, + 1824806551, + 1828271355, + 1831718951, + 1835149305, + 1838562387, + 1841958164, + 1845336603, + 1848697673, + 1852041343, + 1855367580, + 1858676354, + 1861967633, + 1865241387, + 1868497585, + 1871736195, + 1874957188, + 1878160534, + 1881346201, + 1884514160, + 1887664382, + 1890796836, + 1893911493, + 1897008324, + 1900087300, + 1903148391, + 1906191569, + 1909216806, + 1912224072, + 1915213339, + 1918184580, + 1921137766, + 1924072870, + 1926989863, + 1929888719, + 1932769410, + 1935631909, + 1938476189, + 1941302224, + 1944109986, + 1946899450, + 1949670588, + 1952423376, + 1955157787, + 1957873795, + 1960571374, + 1963250500, + 1965911147, + 1968553291, + 1971176905, + 1973781966, + 1976368449, + 1978936330, + 1981485584, + 1984016188, + 1986528117, + 1989021349, + 1991495859, + 1993951624, + 1996388621, + 1998806828, + 2001206221, + 2003586778, + 2005948477, + 2008291295, + 2010615209, + 2012920200, + 2015206244, + 2017473320, + 2019721407, + 2021950483, + 2024160528, + 2026351521, + 2028523441, + 2030676268, + 2032809981, + 2034924561, + 2037019987, + 2039096240, + 2041153301, + 2043191149, + 2045209766, + 2047209132, + 2049189230, + 2051150040, + 2053091543, + 2055013722, + 2056916559, + 2058800035, + 2060664132, + 2062508835, + 2064334123, + 2066139982, + 2067926393, + 2069693341, + 2071440807, + 2073168776, + 2074877232, + 2076566159, + 2078235539, + 2079885359, + 2081515602, + 2083126253, + 2084717297, + 2086288719, + 2087840504, + 2089372637, + 2090885104, + 2092377891, + 2093850984, + 2095304369, + 2096738031, + 2098151959, + 2099546138, + 2100920555, + 2102275198, + 2103610053, + 2104925108, + 2106220351, + 2107495769, + 2108751351, + 2109987084, + 2111202958, + 2112398959, + 2113575079, + 2114731304, + 2115867625, + 2116984030, + 2118080510, + 2119157053, + 2120213650, + 2121250291, + 2122266966, + 2123263665, + 2124240379, + 2125197099, + 2126133816, + 2127050521, + 2127947205, + 2128823861, + 2129680479, + 2130517051, + 2131333571, + 2132130029, + 2132906419, + 2133662733, + 2134398965, + 2135115106, + 2135811152, + 2136487094, + 2137142926, + 2137778643, + 2138394239, + 2138989707, + 2139565042, + 2140120239, + 2140655292, + 2141170196, + 2141664947, + 2142139540, + 2142593970, + 2143028233, + 2143442325, + 2143836243, + 2144209981, + 2144563538, + 2144896909, + 2145210091, + 2145503082, + 2145775879, + 2146028479, + 2146260880, + 2146473079, + 2146665075, + 2146836865, + 2146988449, + 2147119824, + 2147230990, + 2147321945, + 2147392689, + 2147443221, + 2147473541, + 2147483647 +}; + +/* Sine lookup table read */ +static inline int32_t sine_lookup(int idx) { + int32_t s; + int i1; + + i1 = idx & (2 * SINE_NQUART - 1); + if (i1 > SINE_NQUART) + i1 = 2 * SINE_NQUART - i1; + + if (idx > 2 * SINE_NQUART) + s = -sine_table[i1]; + else + s = sine_table[i1]; + + return (s); +} + +/* Compute fixed point sine with table lookup and interpolation */ +int32_t sin_fixed(int32_t w) { + int idx; + int32_t frac, s0, s1, delta; + int64_t sine, idx_tmp; + + /* Q4.28 x Q12.20 -> Q16.48 */ + idx_tmp = (int64_t) w * SINE_C_Q20; + idx = (int) (idx_tmp >> 48); /* Shift to Q0 */ + idx_tmp = idx_tmp >> 17; /* Shift to Q16.31 */ + idx_tmp = idx_tmp - (idx << 31); /* Get fraction */ + frac = (int32_t) idx_tmp; /* Q1.31 */ + s0 = sine_lookup(idx); /* Q1.31 */ + s1 = sine_lookup(idx + 1); /* Q1.31 */ + delta = s1 - s0; /* Q1.31 */ + //sine = (int64_t) frac*delta; /* Q1.31 x Q1.31 -> Q2.62 */ + //sine = (sine >> 31) + s0; /* Q2.31 */ + sine = s0 + q_mults_32x32(frac, delta, 31, 31, 31); /* All Q1.31 */ + return (int32_t) sine; +} + diff --git a/src/tasks/audio.c b/src/tasks/audio.c index ed99806..8dc42ce 100644 --- a/src/tasks/audio.c +++ b/src/tasks/audio.c @@ -64,6 +64,7 @@ int do_task(struct reef *reef) sys_comp_switch_init(); sys_comp_volume_init(); sys_comp_src_init(); + sys_comp_tone_init();
#if 0 /* init static pipeline */