1c72fcc34Sopenharmony_ci/* 2c72fcc34Sopenharmony_ci * Copyright (C) 2015 Caleb Crome 3c72fcc34Sopenharmony_ci * Copyright (C) 2013-2015 Intel Corporation 4c72fcc34Sopenharmony_ci * 5c72fcc34Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 6c72fcc34Sopenharmony_ci * it under the terms of the GNU General Public License as published by 7c72fcc34Sopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8c72fcc34Sopenharmony_ci * (at your option) any later version. 9c72fcc34Sopenharmony_ci * 10c72fcc34Sopenharmony_ci * This program is distributed in the hope that it will be useful, 11c72fcc34Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12c72fcc34Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13c72fcc34Sopenharmony_ci * GNU General Public License for more details. 14c72fcc34Sopenharmony_ci * 15c72fcc34Sopenharmony_ci */ 16c72fcc34Sopenharmony_ci 17c72fcc34Sopenharmony_ci/* 18c72fcc34Sopenharmony_ci * This is a general purpose sine wave generator that will stay stable 19c72fcc34Sopenharmony_ci * for a long time, and with a little renormalization, could stay stay 20c72fcc34Sopenharmony_ci * stable indefinitely 21c72fcc34Sopenharmony_ci */ 22c72fcc34Sopenharmony_ci 23c72fcc34Sopenharmony_ci#include "aconfig.h" 24c72fcc34Sopenharmony_ci 25c72fcc34Sopenharmony_ci#include <stdio.h> 26c72fcc34Sopenharmony_ci#include <stddef.h> 27c72fcc34Sopenharmony_ci#include <stdlib.h> 28c72fcc34Sopenharmony_ci#include <string.h> 29c72fcc34Sopenharmony_ci#include <math.h> 30c72fcc34Sopenharmony_ci#include <stdint.h> 31c72fcc34Sopenharmony_ci#include <stdbool.h> 32c72fcc34Sopenharmony_ci#include <errno.h> 33c72fcc34Sopenharmony_ci 34c72fcc34Sopenharmony_ci#include "gettext.h" 35c72fcc34Sopenharmony_ci#include "common.h" 36c72fcc34Sopenharmony_ci#include "signal.h" 37c72fcc34Sopenharmony_ci 38c72fcc34Sopenharmony_ci/* 39c72fcc34Sopenharmony_ci * Initialize the sine wave generator. 40c72fcc34Sopenharmony_ci * sin_generator: gets initialized by this call. 41c72fcc34Sopenharmony_ci * frequency: the frequency for the sine wave. must be < 0.5*sample_rate 42c72fcc34Sopenharmony_ci * sample_rate: the sample rate... 43c72fcc34Sopenharmony_ci * returns 0 on success, -1 on error. 44c72fcc34Sopenharmony_ci */ 45c72fcc34Sopenharmony_ciint sin_generator_init(struct sin_generator *sg, float magnitude, 46c72fcc34Sopenharmony_ci float frequency, float sample_rate) 47c72fcc34Sopenharmony_ci{ 48c72fcc34Sopenharmony_ci /* angular frequency: cycles/sec / (samp/sec) * rad/cycle = rad/samp */ 49c72fcc34Sopenharmony_ci float w = frequency / sample_rate * 2 * M_PI; 50c72fcc34Sopenharmony_ci if (frequency >= sample_rate / 2) 51c72fcc34Sopenharmony_ci return -1; 52c72fcc34Sopenharmony_ci sg->phasor_real = cos(w); 53c72fcc34Sopenharmony_ci sg->phasor_imag = sin(w); 54c72fcc34Sopenharmony_ci sg->magnitude = magnitude; 55c72fcc34Sopenharmony_ci sg->state_real = 0.0; 56c72fcc34Sopenharmony_ci sg->state_imag = magnitude; 57c72fcc34Sopenharmony_ci sg->frequency = frequency; 58c72fcc34Sopenharmony_ci sg->sample_rate = sample_rate; 59c72fcc34Sopenharmony_ci return 0; 60c72fcc34Sopenharmony_ci} 61c72fcc34Sopenharmony_ci 62c72fcc34Sopenharmony_ci/* 63c72fcc34Sopenharmony_ci * Generates the next sample in the sine wave. 64c72fcc34Sopenharmony_ci * should be much faster than calling a sin function 65c72fcc34Sopenharmony_ci * if it's inlined and optimized. 66c72fcc34Sopenharmony_ci * 67c72fcc34Sopenharmony_ci * returns the next value. no possibility of error. 68c72fcc34Sopenharmony_ci */ 69c72fcc34Sopenharmony_cifloat sin_generator_next_sample(struct sin_generator *sg) 70c72fcc34Sopenharmony_ci{ 71c72fcc34Sopenharmony_ci /* get shorthand to pointers */ 72c72fcc34Sopenharmony_ci const double pr = sg->phasor_real; 73c72fcc34Sopenharmony_ci const double pi = sg->phasor_imag; 74c72fcc34Sopenharmony_ci const double sr = sg->state_real; 75c72fcc34Sopenharmony_ci const double si = sg->state_imag; 76c72fcc34Sopenharmony_ci /* step the phasor -- complex multiply */ 77c72fcc34Sopenharmony_ci sg->state_real = sr * pr - si * pi; 78c72fcc34Sopenharmony_ci sg->state_imag = sr * pi + pr * si; 79c72fcc34Sopenharmony_ci /* return the input value so sine wave starts at exactly 0.0 */ 80c72fcc34Sopenharmony_ci return (float)sr; 81c72fcc34Sopenharmony_ci} 82c72fcc34Sopenharmony_ci 83c72fcc34Sopenharmony_ci/* fills a vector with a sine wave */ 84c72fcc34Sopenharmony_civoid sin_generator_vfill(struct sin_generator *sg, float *buf, int n) 85c72fcc34Sopenharmony_ci{ 86c72fcc34Sopenharmony_ci int i; 87c72fcc34Sopenharmony_ci for (i = 0; i < n; i++) 88c72fcc34Sopenharmony_ci *buf++ = sin_generator_next_sample(sg); 89c72fcc34Sopenharmony_ci} 90c72fcc34Sopenharmony_ci 91c72fcc34Sopenharmony_cistatic int reorder(struct bat *bat, float *val, int frames) 92c72fcc34Sopenharmony_ci{ 93c72fcc34Sopenharmony_ci float *new_buf = NULL; 94c72fcc34Sopenharmony_ci int i, c, bytes; 95c72fcc34Sopenharmony_ci 96c72fcc34Sopenharmony_ci bytes = frames * bat->channels * sizeof(float); 97c72fcc34Sopenharmony_ci 98c72fcc34Sopenharmony_ci new_buf = (float *) malloc(bytes); 99c72fcc34Sopenharmony_ci if (new_buf == NULL) { 100c72fcc34Sopenharmony_ci fprintf(bat->err, _("Not enough memory.\n")); 101c72fcc34Sopenharmony_ci return -ENOMEM; 102c72fcc34Sopenharmony_ci } 103c72fcc34Sopenharmony_ci 104c72fcc34Sopenharmony_ci memcpy(new_buf, val, bytes); 105c72fcc34Sopenharmony_ci for (i = 0; i < frames; i++) 106c72fcc34Sopenharmony_ci for (c = 0; c < bat->channels; c++) 107c72fcc34Sopenharmony_ci val[i * bat->channels + c] = 108c72fcc34Sopenharmony_ci new_buf[c * frames + i]; 109c72fcc34Sopenharmony_ci free(new_buf); 110c72fcc34Sopenharmony_ci 111c72fcc34Sopenharmony_ci return 0; 112c72fcc34Sopenharmony_ci} 113c72fcc34Sopenharmony_ci 114c72fcc34Sopenharmony_cistatic int adjust_waveform(struct bat *bat, float *val, int frames, 115c72fcc34Sopenharmony_ci int channels) 116c72fcc34Sopenharmony_ci{ 117c72fcc34Sopenharmony_ci int i, nsamples, max; 118c72fcc34Sopenharmony_ci float factor, offset = 0.0; 119c72fcc34Sopenharmony_ci 120c72fcc34Sopenharmony_ci switch (bat->format) { 121c72fcc34Sopenharmony_ci case BAT_PCM_FORMAT_U8: 122c72fcc34Sopenharmony_ci max = INT8_MAX; 123c72fcc34Sopenharmony_ci offset = max; /* shift for unsigned format */ 124c72fcc34Sopenharmony_ci break; 125c72fcc34Sopenharmony_ci case BAT_PCM_FORMAT_S16_LE: 126c72fcc34Sopenharmony_ci max = INT16_MAX; 127c72fcc34Sopenharmony_ci break; 128c72fcc34Sopenharmony_ci case BAT_PCM_FORMAT_S24_3LE: 129c72fcc34Sopenharmony_ci max = (1 << 23) - 1; 130c72fcc34Sopenharmony_ci break; 131c72fcc34Sopenharmony_ci case BAT_PCM_FORMAT_S32_LE: 132c72fcc34Sopenharmony_ci max = INT32_MAX; 133c72fcc34Sopenharmony_ci break; 134c72fcc34Sopenharmony_ci default: 135c72fcc34Sopenharmony_ci fprintf(bat->err, _("Invalid PCM format: %d\n"), bat->format); 136c72fcc34Sopenharmony_ci return -EINVAL; 137c72fcc34Sopenharmony_ci } 138c72fcc34Sopenharmony_ci 139c72fcc34Sopenharmony_ci factor = max * RANGE_FACTOR; 140c72fcc34Sopenharmony_ci nsamples = channels * frames; 141c72fcc34Sopenharmony_ci 142c72fcc34Sopenharmony_ci for (i = 0; i < nsamples; i++) 143c72fcc34Sopenharmony_ci val[i] = val[i] * factor + offset; 144c72fcc34Sopenharmony_ci 145c72fcc34Sopenharmony_ci return 0; 146c72fcc34Sopenharmony_ci} 147c72fcc34Sopenharmony_ci 148c72fcc34Sopenharmony_ciint generate_sine_wave(struct bat *bat, int frames, void *buf) 149c72fcc34Sopenharmony_ci{ 150c72fcc34Sopenharmony_ci int err = 0; 151c72fcc34Sopenharmony_ci int c, nsamples; 152c72fcc34Sopenharmony_ci float *sinus_f = NULL; 153c72fcc34Sopenharmony_ci static struct sin_generator sg[MAX_CHANNELS]; 154c72fcc34Sopenharmony_ci 155c72fcc34Sopenharmony_ci nsamples = bat->channels * frames; 156c72fcc34Sopenharmony_ci sinus_f = (float *) malloc(nsamples * sizeof(float)); 157c72fcc34Sopenharmony_ci if (sinus_f == NULL) { 158c72fcc34Sopenharmony_ci fprintf(bat->err, _("Not enough memory.\n")); 159c72fcc34Sopenharmony_ci return -ENOMEM; 160c72fcc34Sopenharmony_ci } 161c72fcc34Sopenharmony_ci 162c72fcc34Sopenharmony_ci for (c = 0; c < bat->channels; c++) { 163c72fcc34Sopenharmony_ci /* initialize static struct at the first time */ 164c72fcc34Sopenharmony_ci if (sg[c].frequency != bat->target_freq[c]) 165c72fcc34Sopenharmony_ci sin_generator_init(&sg[c], 1.0, bat->target_freq[c], 166c72fcc34Sopenharmony_ci bat->rate); 167c72fcc34Sopenharmony_ci /* fill buffer for each channel */ 168c72fcc34Sopenharmony_ci sin_generator_vfill(&sg[c], sinus_f + c * frames, frames); 169c72fcc34Sopenharmony_ci } 170c72fcc34Sopenharmony_ci 171c72fcc34Sopenharmony_ci /* reorder samples to interleaved mode */ 172c72fcc34Sopenharmony_ci err = reorder(bat, sinus_f, frames); 173c72fcc34Sopenharmony_ci if (err != 0) 174c72fcc34Sopenharmony_ci goto exit; 175c72fcc34Sopenharmony_ci 176c72fcc34Sopenharmony_ci /* adjust amplitude and offset of waveform */ 177c72fcc34Sopenharmony_ci err = adjust_waveform(bat, sinus_f, frames, bat->channels); 178c72fcc34Sopenharmony_ci if (err != 0) 179c72fcc34Sopenharmony_ci goto exit; 180c72fcc34Sopenharmony_ci 181c72fcc34Sopenharmony_ci bat->convert_float_to_sample(sinus_f, buf, frames, bat->channels); 182c72fcc34Sopenharmony_ci 183c72fcc34Sopenharmony_ciexit: 184c72fcc34Sopenharmony_ci free(sinus_f); 185c72fcc34Sopenharmony_ci 186c72fcc34Sopenharmony_ci return err; 187c72fcc34Sopenharmony_ci} 188c72fcc34Sopenharmony_ci 189c72fcc34Sopenharmony_ci/* generate single channel sine waveform without sample conversion */ 190c72fcc34Sopenharmony_ciint generate_sine_wave_raw_mono(struct bat *bat, float *buf, 191c72fcc34Sopenharmony_ci float freq, int nsamples) 192c72fcc34Sopenharmony_ci{ 193c72fcc34Sopenharmony_ci int err = 0; 194c72fcc34Sopenharmony_ci struct sin_generator sg; 195c72fcc34Sopenharmony_ci 196c72fcc34Sopenharmony_ci err = sin_generator_init(&sg, 1.0, freq, bat->rate); 197c72fcc34Sopenharmony_ci if (err < 0) 198c72fcc34Sopenharmony_ci return err; 199c72fcc34Sopenharmony_ci sin_generator_vfill(&sg, buf, nsamples); 200c72fcc34Sopenharmony_ci 201c72fcc34Sopenharmony_ci /* adjust amplitude and offset of waveform */ 202c72fcc34Sopenharmony_ci err = adjust_waveform(bat, buf, nsamples, 1); 203c72fcc34Sopenharmony_ci 204c72fcc34Sopenharmony_ci return err; 205c72fcc34Sopenharmony_ci} 206