|
-
August 17th, 2011, 04:01 PM
#1
multitone sine frequencies
I have a program that generates a sine wave. I wanted to know how to generate a multitone wave with 2 frequencies using this program.What has to be changed? Any help would be greatly appreciated.
Code:
static void generate_sine(const snd_pcm_channel_area_t *areas,
snd_pcm_uframes_t offset,
int count, double *_phase)
{
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);
float amplitude_scale = amplitude/8.56;
// 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...", chn , areas[chn].first);
exit(EXIT_FAILURE);
}
samples[chn] = (((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
if ((areas[chn].step % 16) != 0) {
// printf("areas[%i].step == %i, aborting... ", 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 = amplitude_scale * sin(phase) * maxval;
res = fval.i;
} else
res = amplitude_scale * 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;
}
Code:
static int write_loop(snd_pcm_t *handle,
signed short *samples,
snd_pcm_channel_area_t *areas)
{
double phase = 0;
signed short *ptr;
int err, cptr;
while (1) {
generate_sine(areas, 0, period_size, &phase);
ptr = samples;
cptr = period_size;
while (cptr > 0) {
err = snd_pcm_writei(handle, ptr, cptr);
if (err == -EAGAIN)
continue;
if (err < 0) {
if (xrun_recovery(handle, err) < 0) {
printf("Write error: %s ", snd_strerror(err));
exit(EXIT_FAILURE);
}
break; /* skip one period */
}
ptr += err * channels;
cptr -= err;
}
}
}
Code:
int main(int argc, char *argv[])
{
snd_pcm_t *handle;
int err;
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;
int method = 0;
signed short *samples;
unsigned int chn;
snd_pcm_channel_area_t *areas;
snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_sw_params_alloca(&swparams);
err = snd_output_stdio_attach(&output, stdout, 0);
printf( "snd_output_stdio_attach err=%d\n", err);
err = snd_pcm_open(&hspdif, device, SND_PCM_STREAM_PLAYBACK, 0);
printf( "snd_pcm_open err=%d\n", err);
err = set_hwparams(hspdif, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
printf( "set_hwparams err=%d\n", err);
err = set_swparams(hspdif, swparams);
printf( "set_swparams err=%d\n", err);
samples = new signed short [period_size * channels * snd_pcm_format_physical_width(format)];
printf( "samples array_size=%d\n", int( period_size * channels * snd_pcm_format_physical_width(format)) );
areas = new snd_pcm_channel_area_t [channels];
printf( "areas channels=%d\n", channels);
for (unsigned int chn = 0; chn < channels; chn++) {
areas[chn].addr = samples;
areas[chn].first = chn * snd_pcm_format_physical_width(format);
areas[chn].step = channels * snd_pcm_format_physical_width(format);
}
err = transfer_methods[method].transfer_loop(handle, samples, areas);
if (err < 0)
printf("Transfer failed: %s", snd_strerror(err));
delete [] areas;
delete []samples;
snd_pcm_close(handle);
return 0;
}
-
August 17th, 2011, 04:51 PM
#2
Re: multitone sine frequencies
Long story short, if you are pleased to explain me this function prototype
static int write_loop(snd_pcm_t *handle,
signed short *samples,
snd_pcm_channel_area_t *areas)
from its use of return type to each definition of its parameters, as well as the details of function scope, I would definitely try to help you finish your project./
-
August 18th, 2011, 12:03 AM
#3
Re: multitone sine frequencies
 Originally Posted by ogopa
Any help would be greatly appreciated.
You just superimpose the two waves. This means you add their amplitudes at each sampling point in time.
-
August 19th, 2011, 08:24 AM
#4
Re: multitone sine frequencies
I got the answer. I had to add the two amplitudes as well as two sin(phase).
Solution: static void generate_multi(snd_pcm_uframes_t offset, int count, double *_phase, double *_phase2)
{
static double max_phase = 2. * M_PI;
double phase = *_phase;
double phase2 = *_phase2;
double step = max_phase*freq/(double)rate;
double step2 = max_phase*freq2/(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);
float amplitude_scale = ampl/8.56;
float amplitude_scale_2 = ampl2/8.56;
// 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...", chn , areas[chn].first);
exit(EXIT_FAILURE);
}
samples[chn] = (((unsigned char *)areas[chn].addr) + (areas[chn].first / 8));
if ((areas[chn].step % 16) != 0) {
printf("areas[%i].step == %i, aborting... ", 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 = (amplitude_scale * sin(phase) + amplitude_scale_2 * sin(phase2)) * maxval/2;
res = fval.i;
} else
res = (amplitude_scale * sin(phase) + amplitude_scale_2 * sin(phase2)) * maxval/2;
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;
phase2 += step2;
if (phase >= max_phase)
phase -= max_phase;
if (phase2 >= max_phase)
phase2 -= max_phase;
}
*_phase = phase;
*_phase2 = phase2;
}
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|