78 lines
2.5 KiB
C
78 lines
2.5 KiB
C
#include "ac108_help.h"
|
|
|
|
void generate_sine(const snd_pcm_channel_area_t *areas,
|
|
snd_pcm_uframes_t offset,
|
|
int count, double *_phase)
|
|
{
|
|
snd_pcm_format_t format = SND_PCM_FORMAT_S32; /* sample format */
|
|
unsigned int rate = 16000; /* stream rate */
|
|
unsigned int channels = 4; /* count of channels */
|
|
unsigned int buffer_time = 500000; /* ring buffer length in us */
|
|
unsigned int period_time = 100000; /* period time in us */
|
|
double freq = 160; /* sinusoidal wave frequency in Hz */
|
|
int verbose = 0; /* verbose flag */
|
|
int resample = 1; /* enable alsa-lib resampling */
|
|
int period_event = 0; /* produce poll event after each period */
|
|
|
|
static double max_phase = 2. * M_PI;
|
|
double phase = *_phase;
|
|
double step = max_phase*freq/(double)rate;
|
|
unsigned char *samples[channels];
|
|
int steps[channels];
|
|
unsigned int chn;
|
|
int format_bits = snd_pcm_format_width(format);
|
|
unsigned int maxval = (1 << (format_bits - 1)) - 1;
|
|
int bps = format_bits / 8; /* bytes per sample */
|
|
int phys_bps = snd_pcm_format_physical_width(format) / 8;
|
|
int big_endian = snd_pcm_format_big_endian(format) == 1;
|
|
int to_unsigned = snd_pcm_format_unsigned(format) == 1;
|
|
int is_float = (format == SND_PCM_FORMAT_FLOAT_LE ||
|
|
format == SND_PCM_FORMAT_FLOAT_BE);
|
|
|
|
/* verify and prepare the contents of areas */
|
|
for (chn = 0; chn < channels; chn++) {
|
|
if ((areas[chn].first % 8) != 0) {
|
|
printf("areas[%i].first == %i, aborting...\n", chn, areas[chn].first);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
samples[chn] = /*(signed short *)*/(((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
|
|
if ((areas[chn].step % 16) != 0) {
|
|
printf("areas[%i].step == %i, aborting...\n", chn, areas[chn].step);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
steps[chn] = areas[chn].step / 8;
|
|
samples[chn] += offset * steps[chn];
|
|
}
|
|
/* fill the channel areas */
|
|
while (count-- > 0) {
|
|
union {
|
|
float f;
|
|
int i;
|
|
} fval;
|
|
int res, i;
|
|
if (is_float) {
|
|
fval.f = sin(phase);
|
|
res = fval.i;
|
|
} else
|
|
res = sin(phase) * maxval;
|
|
if (to_unsigned)
|
|
res ^= 1U << (format_bits - 1);
|
|
for (chn = 0; chn < channels; chn++) {
|
|
/* Generate data in native endian format */
|
|
if (big_endian) {
|
|
for (i = 0; i < bps; i++)
|
|
*(samples[chn] + phys_bps - 1 - i) = (res >> i * 8) & 0xff;
|
|
} else {
|
|
for (i = 0; i < bps; i++)
|
|
*(samples[chn] + i) = (res >> i * 8) & 0xff;
|
|
}
|
|
samples[chn] += steps[chn];
|
|
}
|
|
phase += step;
|
|
if (phase >= max_phase)
|
|
phase -= max_phase;
|
|
}
|
|
*_phase = phase;
|
|
}
|
|
|