---
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(a)linux.intel.com>
+ * Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
+ * Keyon Jie <yang.jie(a)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(a)linux.intel.com>
+ * Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
+ * Keyon Jie <yang.jie(a)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(a)linux.intel.com>
+ * Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
+ * Keyon Jie <yang.jie(a)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(a)linux.intel.com>
+ * Liam Girdwood <liam.r.girdwood(a)linux.intel.com>
+ * Keyon Jie <yang.jie(a)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 */
--
2.11.0