kav17
Posts: 8
Joined: Fri Jul 05, 2013 4:56 am

Code to generate real-time sound

Sat Sep 28, 2013 3:05 am

Hi everyone! I searched this for several months now and still do not find. I need a c++ codeto generate pure tones, not play sounds already created, I need to generate beeps with the frequency and duration indicated, is there any way to do this?? Thank you! : D

User avatar
davef21370
Posts: 897
Joined: Fri Sep 21, 2012 4:13 pm
Location: Earth But Not Grounded

Re: Code to generate real-time sound

Mon Sep 30, 2013 5:37 pm

You could build a WAV format file and play that, simple(ish) format, have a look here...
https://ccrma.stanford.edu/courses/422/ ... aveFormat/

Dave.
Apple say... Monkey do !!

nid69ita
Posts: 25
Joined: Sun Jul 07, 2013 8:08 pm

Re: Code to generate real-time sound

Wed Oct 02, 2013 12:08 pm

kav17 wrote:Hi everyone! I searched this for several months now and still do not find. I need a c++ codeto generate pure tones, not play sounds already created, I need to generate beeps with the frequency and duration indicated, is there any way to do this?? Thank you! : D
Using internal sound system of raspy or using an external buzzer linked to GPIO?

if first, I see this (about portaudio library) in this link:
http://www.drdobbs.com/embedded-systems ... /240158605

If second, you can use wiringPi
http://wiringpi.com/reference/software-tone-library/

User avatar
RichR
Posts: 5
Joined: Sat Dec 06, 2014 6:10 pm

Re: Code to generate real-time sound

Mon Dec 15, 2014 4:08 pm

Would a call to speaker-test from your C++ app work?
speaker-test -t sine -f 440 -c 2 -s 1
I have tried to get portaudio to work correctly with ALSA on my Pi, but without success.

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 4:57 pm

hello,
I have the same problem as posted by the OP, but can't find a solution to generate and play a tone on the fly in a C program, e.g., by
PlayTone(frequency [Hz], duration [ms])
perhaps
PlayTone (440, 250) // 440 Hz for 250ms
Output should be standard audio output according to current settings (headphone jacks or HDMI).
who knows such a lib by his own experience, just to be #included, and to be used out of the box?

BTW,
speaker-test -t sine -f 440 -s 1
works, but I need also durations far less than 1sec, and I don't see how to generate such short tones with speaker-test, perhaps some one ould tell me how to, if possible?
- Tim

User avatar
PeterO
Posts: 5888
Joined: Sun Jul 22, 2012 4:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 5:25 pm

Have a look at http://www.alsa-project.org/alsa-doc/al ... ample.html

There's code in there to generate and play a 440Hz tone.

If you want to start and stop the tone you can either
1) Write zeros when you want silence
2) Close the alsa device when you have no sound to play and reopen it when you want o start playing a sound again.

PeterO

PS;

There is a simpler example : http://www.alsa-project.org/alsa-doc/al ... ample.html but it writes random data, I'm sure you can workout how to integrate the sine tone generating code from the bigger example.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 5:47 pm

thank you. The code is admittedly a bit longer than just

Code: Select all

PlayTone(freq, duration)
As a bloody beginner I have a lot off issues reading such a big bunch of code, that's why I asked for a lib just to # include and then just use sth like

Code: Select all

PlayTone(freq, duration)
I actually understand nothing of all the code lines you linked to, I just wanted to use a simple function call (even without understanding how it finally works) -
but even if I copy and paste all this additionally into my own current code

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include "../include/asoundlib.h"
#include <sys/time.h>
#include <math.h>
static char *device = "plughw:0,0";                     /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16;    /* sample format */
static unsigned int rate = 44100;                       /* stream rate */
static unsigned int channels = 1;                       /* count of channels */
static unsigned int buffer_time = 500000;               /* ring buffer length in us */
static unsigned int period_time = 100000;               /* period time in us */
static double freq = 440;                               /* sinusoidal wave frequency in Hz */
static int verbose = 0;                                 /* verbose flag */
static int resample = 1;                                /* enable alsa-lib resampling */
static int period_event = 0;                            /* produce poll event after each period */
static snd_pcm_sframes_t buffer_size;
static snd_pcm_sframes_t period_size;
static snd_output_t *output = NULL;
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);
        /* 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;
}
static int set_hwparams(snd_pcm_t *handle,
                        snd_pcm_hw_params_t *params,
                        snd_pcm_access_t access)
{
        unsigned int rrate;
        snd_pcm_uframes_t size;
        int err, dir;
        /* choose all parameters */
        err = snd_pcm_hw_params_any(handle, params);
        if (err < 0) {
                printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
                return err;
        }
        /* set hardware resampling */
        err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
        if (err < 0) {
                printf("Resampling setup failed for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* set the interleaved read/write format */
        err = snd_pcm_hw_params_set_access(handle, params, access);
        if (err < 0) {
                printf("Access type not available for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* set the sample format */
        err = snd_pcm_hw_params_set_format(handle, params, format);
        if (err < 0) {
                printf("Sample format not available for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* set the count of channels */
        err = snd_pcm_hw_params_set_channels(handle, params, channels);
        if (err < 0) {
                printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
                return err;
        }
        /* set the stream rate */
        rrate = rate;
        err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
        if (err < 0) {
                printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
                return err;
        }
        if (rrate != rate) {
                printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
                return -EINVAL;
        }
        /* set the buffer time */
        err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
        if (err < 0) {
                printf("Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
                return err;
        }
        err = snd_pcm_hw_params_get_buffer_size(params, &size);
        if (err < 0) {
                printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
                return err;
        }
        buffer_size = size;
        /* set the period time */
        err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
        if (err < 0) {
                printf("Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
                return err;
        }
        err = snd_pcm_hw_params_get_period_size(params, &size, &dir);
        if (err < 0) {
                printf("Unable to get period size for playback: %s\n", snd_strerror(err));
                return err;
        }
        period_size = size;
        /* write the parameters to device */
        err = snd_pcm_hw_params(handle, params);
        if (err < 0) {
                printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
                return err;
        }
        return 0;
}
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams)
{
        int err;
        /* get the current swparams */
        err = snd_pcm_sw_params_current(handle, swparams);
        if (err < 0) {
                printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* start the transfer when the buffer is almost full: */
        /* (buffer_size / avail_min) * avail_min */
        err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
        if (err < 0) {
                printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* allow the transfer when at least period_size samples can be processed */
        /* or disable this mechanism when period event is enabled (aka interrupt like style processing) */
        err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
        if (err < 0) {
                printf("Unable to set avail min for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* enable period events when requested */
        if (period_event) {
                err = snd_pcm_sw_params_set_period_event(handle, swparams, 1);
                if (err < 0) {
                        printf("Unable to set period event: %s\n", snd_strerror(err));
                        return err;
                }
        }
        /* write the parameters to the playback device */
        err = snd_pcm_sw_params(handle, swparams);
        if (err < 0) {
                printf("Unable to set sw params for playback: %s\n", snd_strerror(err));
                return err;
        }
        return 0;
}
/*
 *   Underrun and suspend recovery
 */
 
static int xrun_recovery(snd_pcm_t *handle, int err)
{
        if (verbose)
                printf("stream recovery\n");
        if (err == -EPIPE) {    /* under-run */
                err = snd_pcm_prepare(handle);
                if (err < 0)
                        printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
                return 0;
        } else if (err == -ESTRPIPE) {
                while ((err = snd_pcm_resume(handle)) == -EAGAIN)
                        sleep(1);       /* wait until the suspend flag is released */
                if (err < 0) {
                        err = snd_pcm_prepare(handle);
                        if (err < 0)
                                printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
                }
                return 0;
        }
        return err;
}
/*
 *   Transfer method - write only
 */
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\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                break;  /* skip one period */
                        }
                        ptr += err * channels;
                        cptr -= err;
                }
        }
}
 
/*
 *   Transfer method - write and wait for room in buffer using poll
 */
static int wait_for_poll(snd_pcm_t *handle, struct pollfd *ufds, unsigned int count)
{
        unsigned short revents;
        while (1) {
                poll(ufds, count, -1);
                snd_pcm_poll_descriptors_revents(handle, ufds, count, &revents);
                if (revents & POLLERR)
                        return -EIO;
                if (revents & POLLOUT)
                        return 0;
        }
}
static int write_and_poll_loop(snd_pcm_t *handle,
                               signed short *samples,
                               snd_pcm_channel_area_t *areas)
{
        struct pollfd *ufds;
        double phase = 0;
        signed short *ptr;
        int err, count, cptr, init;
        count = snd_pcm_poll_descriptors_count (handle);
        if (count <= 0) {
                printf("Invalid poll descriptors count\n");
                return count;
        }
        ufds = malloc(sizeof(struct pollfd) * count);
        if (ufds == NULL) {
                printf("No enough memory\n");
                return -ENOMEM;
        }
        if ((err = snd_pcm_poll_descriptors(handle, ufds, count)) < 0) {
                printf("Unable to obtain poll descriptors for playback: %s\n", snd_strerror(err));
                return err;
        }
        init = 1;
        while (1) {
                if (!init) {
                        err = wait_for_poll(handle, ufds, count);
                        if (err < 0) {
                                if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN ||
                                    snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED) {
                                        err = snd_pcm_state(handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                        if (xrun_recovery(handle, err) < 0) {
                                                printf("Write error: %s\n", snd_strerror(err));
                                                exit(EXIT_FAILURE);
                                        }
                                        init = 1;
                                } else {
                                        printf("Wait for poll failed\n");
                                        return err;
                                }
                        }
                }
                generate_sine(areas, 0, period_size, &phase);
                ptr = samples;
                cptr = period_size;
                while (cptr > 0) {
                        err = snd_pcm_writei(handle, ptr, cptr);
                        if (err < 0) {
                                if (xrun_recovery(handle, err) < 0) {
                                        printf("Write error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                init = 1;
                                break;  /* skip one period */
                        }
                        if (snd_pcm_state(handle) == SND_PCM_STATE_RUNNING)
                                init = 0;
                        ptr += err * channels;
                        cptr -= err;
                        if (cptr == 0)
                                break;
                        /* it is possible, that the initial buffer cannot store */
                        /* all data from the last period, so wait awhile */
                        err = wait_for_poll(handle, ufds, count);
                        if (err < 0) {
                                if (snd_pcm_state(handle) == SND_PCM_STATE_XRUN ||
                                    snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED) {
                                        err = snd_pcm_state(handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
                                        if (xrun_recovery(handle, err) < 0) {
                                                printf("Write error: %s\n", snd_strerror(err));
                                                exit(EXIT_FAILURE);
                                        }
                                        init = 1;
                                } else {
                                        printf("Wait for poll failed\n");
                                        return err;
                                }
                        }
                }
        }
}
/*
 *   Transfer method - asynchronous notification
 */
struct async_private_data {
        signed short *samples;
        snd_pcm_channel_area_t *areas;
        double phase;
};
static void async_callback(snd_async_handler_t *ahandler)
{
        snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
        struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
        signed short *samples = data->samples;
        snd_pcm_channel_area_t *areas = data->areas;
        snd_pcm_sframes_t avail;
        int err;
        
        avail = snd_pcm_avail_update(handle);
        while (avail >= period_size) {
                generate_sine(areas, 0, period_size, &data->phase);
                err = snd_pcm_writei(handle, samples, period_size);
                if (err < 0) {
                        printf("Write error: %s\n", snd_strerror(err));
                        exit(EXIT_FAILURE);
                }
                if (err != period_size) {
                        printf("Write error: written %i expected %li\n", err, period_size);
                        exit(EXIT_FAILURE);
                }
                avail = snd_pcm_avail_update(handle);
        }
}
static int async_loop(snd_pcm_t *handle,
                      signed short *samples,
                      snd_pcm_channel_area_t *areas)
{
        struct async_private_data data;
        snd_async_handler_t *ahandler;
        int err, count;
        data.samples = samples;
        data.areas = areas;
        data.phase = 0;
        err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, &data);
        if (err < 0) {
                printf("Unable to register async handler\n");
                exit(EXIT_FAILURE);
        }
        for (count = 0; count < 2; count++) {
                generate_sine(areas, 0, period_size, &data.phase);
                err = snd_pcm_writei(handle, samples, period_size);
                if (err < 0) {
                        printf("Initial write error: %s\n", snd_strerror(err));
                        exit(EXIT_FAILURE);
                }
                if (err != period_size) {
                        printf("Initial write error: written %i expected %li\n", err, period_size);
                        exit(EXIT_FAILURE);
                }
        }
        if (snd_pcm_state(handle) == SND_PCM_STATE_PREPARED) {
                err = snd_pcm_start(handle);
                if (err < 0) {
                        printf("Start error: %s\n", snd_strerror(err));
                        exit(EXIT_FAILURE);
                }
        }
        /* because all other work is done in the signal handler,
           suspend the process */
        while (1) {
                sleep(1);
        }
}
/*
 *   Transfer method - asynchronous notification + direct write
 */
static void async_direct_callback(snd_async_handler_t *ahandler)
{
        snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler);
        struct async_private_data *data = snd_async_handler_get_callback_private(ahandler);
        const snd_pcm_channel_area_t *my_areas;
        snd_pcm_uframes_t offset, frames, size;
        snd_pcm_sframes_t avail, commitres;
        snd_pcm_state_t state;
        int first = 0, err;
        
        while (1) {
                state = snd_pcm_state(handle);
                if (state == SND_PCM_STATE_XRUN) {
                        err = xrun_recovery(handle, -EPIPE);
                        if (err < 0) {
                                printf("XRUN recovery failed: %s\n", snd_strerror(err));
                                exit(EXIT_FAILURE);
                        }
                        first = 1;
                } else if (state == SND_PCM_STATE_SUSPENDED) {
                        err = xrun_recovery(handle, -ESTRPIPE);
                        if (err < 0) {
                                printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
                                exit(EXIT_FAILURE);
                        }
                }
                avail = snd_pcm_avail_update(handle);
                if (avail < 0) {
                        err = xrun_recovery(handle, avail);
                        if (err < 0) {
                                printf("avail update failed: %s\n", snd_strerror(err));
                                exit(EXIT_FAILURE);
                        }
                        first = 1;
                        continue;
                }
                if (avail < period_size) {
                        if (first) {
                                first = 0;
                                err = snd_pcm_start(handle);
                                if (err < 0) {
                                        printf("Start error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                        } else {
                                break;
                        }
                        continue;
                }
                size = period_size;
                while (size > 0) {
                        frames = size;
                        err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
                        if (err < 0) {
                                if ((err = xrun_recovery(handle, err)) < 0) {
                                        printf("MMAP begin avail error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                first = 1;
                        }
                        generate_sine(my_areas, offset, frames, &data->phase);
                        commitres = snd_pcm_mmap_commit(handle, offset, frames);
                        if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
                                if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                        printf("MMAP commit error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                first = 1;
                        }
                        size -= frames;
                }
        }
}
static int async_direct_loop(snd_pcm_t *handle,
                             signed short *samples ATTRIBUTE_UNUSED,
                             snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED)
{
        struct async_private_data data;
        snd_async_handler_t *ahandler;
        const snd_pcm_channel_area_t *my_areas;
        snd_pcm_uframes_t offset, frames, size;
        snd_pcm_sframes_t commitres;
        int err, count;
        data.samples = NULL;    /* we do not require the global sample area for direct write */
        data.areas = NULL;      /* we do not require the global areas for direct write */
        data.phase = 0;
        err = snd_async_add_pcm_handler(&ahandler, handle, async_direct_callback, &data);
        if (err < 0) {
                printf("Unable to register async handler\n");
                exit(EXIT_FAILURE);
        }
        for (count = 0; count < 2; count++) {
                size = period_size;
                while (size > 0) {
                        frames = size;
                        err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
                        if (err < 0) {
                                if ((err = xrun_recovery(handle, err)) < 0) {
                                        printf("MMAP begin avail error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                        }
                        generate_sine(my_areas, offset, frames, &data.phase);
                        commitres = snd_pcm_mmap_commit(handle, offset, frames);
                        if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
                                if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                        printf("MMAP commit error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                        }
                        size -= frames;
                }
        }
        err = snd_pcm_start(handle);
        if (err < 0) {
                printf("Start error: %s\n", snd_strerror(err));
                exit(EXIT_FAILURE);
        }
        /* because all other work is done in the signal handler,
           suspend the process */
        while (1) {
                sleep(1);
        }
}
/*
 *   Transfer method - direct write only
 */
static int direct_loop(snd_pcm_t *handle,
                       signed short *samples ATTRIBUTE_UNUSED,
                       snd_pcm_channel_area_t *areas ATTRIBUTE_UNUSED)
{
        double phase = 0;
        const snd_pcm_channel_area_t *my_areas;
        snd_pcm_uframes_t offset, frames, size;
        snd_pcm_sframes_t avail, commitres;
        snd_pcm_state_t state;
        int err, first = 1;
        while (1) {
                state = snd_pcm_state(handle);
                if (state == SND_PCM_STATE_XRUN) {
                        err = xrun_recovery(handle, -EPIPE);
                        if (err < 0) {
                                printf("XRUN recovery failed: %s\n", snd_strerror(err));
                                return err;
                        }
                        first = 1;
                } else if (state == SND_PCM_STATE_SUSPENDED) {
                        err = xrun_recovery(handle, -ESTRPIPE);
                        if (err < 0) {
                                printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
                                return err;
                        }
                }
                avail = snd_pcm_avail_update(handle);
                if (avail < 0) {
                        err = xrun_recovery(handle, avail);
                        if (err < 0) {
                                printf("avail update failed: %s\n", snd_strerror(err));
                                return err;
                        }
                        first = 1;
                        continue;
                }
                if (avail < period_size) {
                        if (first) {
                                first = 0;
                                err = snd_pcm_start(handle);
                                if (err < 0) {
                                        printf("Start error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                        } else {
                                err = snd_pcm_wait(handle, -1);
                                if (err < 0) {
                                        if ((err = xrun_recovery(handle, err)) < 0) {
                                                printf("snd_pcm_wait error: %s\n", snd_strerror(err));
                                                exit(EXIT_FAILURE);
                                        }
                                        first = 1;
                                }
                        }
                        continue;
                }
                size = period_size;
                while (size > 0) {
                        frames = size;
                        err = snd_pcm_mmap_begin(handle, &my_areas, &offset, &frames);
                        if (err < 0) {
                                if ((err = xrun_recovery(handle, err)) < 0) {
                                        printf("MMAP begin avail error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                first = 1;
                        }
                        generate_sine(my_areas, offset, frames, &phase);
                        commitres = snd_pcm_mmap_commit(handle, offset, frames);
                        if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
                                if ((err = xrun_recovery(handle, commitres >= 0 ? -EPIPE : commitres)) < 0) {
                                        printf("MMAP commit error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                first = 1;
                        }
                        size -= frames;
                }
        }
}
 
/*
 *   Transfer method - direct write only using mmap_write functions
 */
static int direct_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_mmap_writei(handle, ptr, cptr);
                        if (err == -EAGAIN)
                                continue;
                        if (err < 0) {
                                if (xrun_recovery(handle, err) < 0) {
                                        printf("Write error: %s\n", snd_strerror(err));
                                        exit(EXIT_FAILURE);
                                }
                                break;  /* skip one period */
                        }
                        ptr += err * channels;
                        cptr -= err;
                }
        }
}
 
/*
 *
 */
struct transfer_method {
        const char *name;
        snd_pcm_access_t access;
        int (*transfer_loop)(snd_pcm_t *handle,
                             signed short *samples,
                             snd_pcm_channel_area_t *areas);
};
static struct transfer_method transfer_methods[] = {
        { "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop },
        { "write_and_poll", SND_PCM_ACCESS_RW_INTERLEAVED, write_and_poll_loop },
        { "async", SND_PCM_ACCESS_RW_INTERLEAVED, async_loop },
        { "async_direct", SND_PCM_ACCESS_MMAP_INTERLEAVED, async_direct_loop },
        { "direct_interleaved", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_loop },
        { "direct_noninterleaved", SND_PCM_ACCESS_MMAP_NONINTERLEAVED, direct_loop },
        { "direct_write", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_write_loop },
        { NULL, SND_PCM_ACCESS_RW_INTERLEAVED, NULL }
};
static void help(void)
{
        int k;
        printf(
"Usage: pcm [OPTION]... [FILE]...\n"
"-h,--help      help\n"
"-D,--device    playback device\n"
"-r,--rate      stream rate in Hz\n"
"-c,--channels  count of channels in stream\n"
"-f,--frequency sine wave frequency in Hz\n"
"-b,--buffer    ring buffer size in us\n"
"-p,--period    period size in us\n"
"-m,--method    transfer method\n"
"-o,--format    sample format\n"
"-v,--verbose   show the PCM setup parameters\n"
"-n,--noresample  do not resample\n"
"-e,--pevent    enable poll event after each period\n"
"\n");
        printf("Recognized sample formats are:");
        for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
                const char *s = snd_pcm_format_name(k);
                if (s)
                        printf(" %s", s);
        }
        printf("\n");
        printf("Recognized transfer methods are:");
        for (k = 0; transfer_methods[k].name; k++)
                printf(" %s", transfer_methods[k].name);
        printf("\n");
}
or even this shorter version instead

Code: Select all

/*
 *  This extra small demo sends a random samples to your speakers.
 */
#include "../include/asoundlib.h"
static char *device = "default";                        /* playback device */
snd_output_t *output = NULL;
unsigned char buffer[16*1024];                          /* some random data */
int main(void)
{
        int err;
        unsigned int i;
        snd_pcm_t *handle;
        snd_pcm_sframes_t frames;
        for (i = 0; i < sizeof(buffer); i++)
                buffer[i] = random() & 0xff;
        if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
                printf("Playback open error: %s\n", snd_strerror(err));
                exit(EXIT_FAILURE);
        }
        if ((err = snd_pcm_set_params(handle,
                                      SND_PCM_FORMAT_U8,
                                      SND_PCM_ACCESS_RW_INTERLEAVED,
                                      1,
                                      48000,
                                      1,
                                      500000)) < 0) {   /* 0.5sec */
                printf("Playback open error: %s\n", snd_strerror(err));
                exit(EXIT_FAILURE);
        }
        for (i = 0; i < 16; i++) {
                frames = snd_pcm_writei(handle, buffer, sizeof(buffer));
                if (frames < 0)
                        frames = snd_pcm_recover(handle, frames, 0);
                if (frames < 0) {
                        printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
                        break;
                }
                if (frames > 0 && frames < (long)sizeof(buffer))
                        printf("Short write (expected %li, wrote %li)\n", (long)sizeof(buffer), frames);
        }
        snd_pcm_close(handle);
        return 0;
}

where would be the part for something like the function call like this

Code: Select all

PlayTone(freq, duration) 
which I would be able to use then for every single tone to play
:?:
- Tim

User avatar
PeterO
Posts: 5888
Joined: Sun Jul 22, 2012 4:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:05 pm

tito-t wrote: I actually understand nothing of all the code lines you linked to,
Sorry, I assumed you actually knew C !
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:10 pm

no, I am learning, slowly, step by step, that's why I wrote
hello,
I have the same problem as posted by the OP, but can't find a solution to generate and play a tone on the fly in a C program, e.g., by
PlayTone(frequency [Hz], duration [ms])
perhaps
PlayTone (440, 250) // 440 Hz for 250ms
Output should be standard audio output according to current settings (headphone jacks or HDMI).
who knows such a lib by his own experience, just to be #included, and to be used out of the box?

BTW,
speaker-test -t sine -f 440 -s 1
works, but I need also durations far less than 1sec, and I don't see how to generate such short tones with speaker-test, perhaps some one ould tell me how to, if possible?
As a bloody beginner I have a lot off issues reading such a big bunch of code, that's why I asked for a lib just to # include and then just use sth like

Code: Select all

PlayTone(freq, duration)

so this is still what I need:
a lib just to #include and then just use sth like

Code: Select all

PlayTone(freq, duration)
- Tim

User avatar
PeterO
Posts: 5888
Joined: Sun Jul 22, 2012 4:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:17 pm

Ok, this might be more appropriate for you then..

http://wiki.libsdl.org/FrontPage and
http://wiki.libsdl.org/CategoryAudio

But you are still going to have to compute an array of sample values to pass to the SDL_LoadWAV function. That is a job for your "PlayTone()" function.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:26 pm

no, I don't need an encyclopedia, I think you missed the part in my post where I wrote
that's why I asked for a lib just to # include and then just use sth like

Code: Select all

 PlayTone(freq, duration)
(...)
who knows such a lib by his own experience, just to be #included, and to be used out of the box?
so I look for something like

Code: Select all

#include <tonelib.h> // or however the lib is called

//...
int main() {
   PlayTone(440, 250);
//...
}
- Tim

User avatar
PeterO
Posts: 5888
Joined: Sun Jul 22, 2012 4:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:32 pm

I've shown you all the information you need to solve your problem two ways but since you aren't willing to put in any effort to learn how to program in C I'm not willing to put in any effort to help you further,

Whatever !

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:39 pm

thank you for your input, but as I wrote right from the start, for the moment I need a function and a lib to #include which will work out of the box, and I also asked for a lib someone would already know from his own experience which would work like this.
I think you missed that this was a compelling condition.
So this sort of

Code: Select all

PlayTone(440, 250);
must already be provided.
- Tim

BMS Doug
Posts: 3824
Joined: Thu Mar 27, 2014 2:42 pm
Location: London, UK

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:48 pm

tito-t wrote: I think you missed that this was a compelling condition.
I think that you are missing that the primary focus of the raspberry pi is education, as such the majority of the forum regulars are happy to help people learn anything.

Spoonfeeding completed solutions that don't teach the person anything is not a favoured solution for most forum regulars.

You have witness this process, most of the other forum regulars will have a similar attitude to PeterO.
Doug.
Building Management Systems Engineer.

User avatar
PeterO
Posts: 5888
Joined: Sun Jul 22, 2012 4:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:53 pm

Exactly Doug. What he hasn't realised is while he's been asking for the same thing over and over, I've actually spent some time looking to see if I could find a library that provides the simple function he's after.
So far I've not found anything so I've pointed him at the next best things I could find.
But that's it.
With a bit of effort and help he could have had a working solution by now!
PeterO
Last edited by PeterO on Tue Oct 04, 2016 6:59 pm, edited 1 time in total.
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 6:58 pm

I don't want to discuss about my wish, I stated that I need this function and I think I would not be the first one who is looking for sth likt this - see above, the thread opening post of the original poster.
I can't believe that after so many years of Linux there shouldn't be a lib like this. Finally it's just about a question about the usage of gpio pins, no one who asks about how to use soft pwm would be adviced to write his own pigpio or wiringPi, the answer would be: there is the pigpio lib and the wiringPi lib, and you can use it by the function SoftPWM(...)
So if no one knows a solution to my question, ok, he is not forsed to answer and - above all - not asked to bash or to lecture me (as it often seems to be a common practice of some forum's members).
But any really helpful hints to such libs are very much appreciated. Perhaps someons is eventually supposed to know what I am searching for.

So I am still looking forward to a lib just to # include and then just use sth like

Code: Select all

PlayTone(freq, duration)
Last edited by tito-t on Tue Oct 04, 2016 7:02 pm, edited 1 time in total.
- Tim

User avatar
kusti8
Posts: 3439
Joined: Sat Dec 21, 2013 5:29 pm
Location: USA

Re: Code to generate real-time sound

Tue Oct 04, 2016 7:01 pm

You also need to realize that C isn't a simple, there's a library for everything, quick scripting language. It's great for robustness, speed or power, but it is low level and you're never going to find a random generate tone function. That's why high level languages were made like Python, which is easier to learn but of course slow and less powerful, but does come with many libraries.
There are 10 types of people: those who understand binary and those who don't.

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 7:03 pm

please read a little closer, I wrote
I don't want to discuss about my wish, I stated that I need this function and I think I would not be the first one who is looking for sth like this - see above, the thread opening post of the original poster.
...
So if no one knows a solution to my question, ok, he is not forced to answer and - above all - not asked to bash or to lecture me (as it often seems to be a common practice of some forum's members).
But any really helpful hints to such libs are very much appreciated. Perhaps someone is eventually supposed to know what I am searching for.
So a lib to #include plus this sort of

Code: Select all

PlayTone(440, 250);
to work out of the box must already be provided.
- Tim

User avatar
rpdom
Posts: 17196
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Code to generate real-time sound

Tue Oct 04, 2016 7:29 pm

tito-t wrote:please read a little closer, I wrote
I don't want to discuss about my wish, I stated that I need this function and I think I would not be the first one who is looking for sth like this - see above, the thread opening post of the original poster.
...
So if no one knows a solution to my question, ok, he is not forced to answer and - above all - not asked to bash or to lecture me (as it often seems to be a common practice of some forum's members).
But any really helpful hints to such libs are very much appreciated. Perhaps someone is eventually supposed to know what I am searching for.
So a lib to #include plus this sort of

Code: Select all

PlayTone(440, 250);
to work out of the box must already be provided.
I think your question has been answered many times. The simple answer is "No, there is no readily available library to do your homework for you". You just don't want to accept that answer and prefer to attack people who are trying to help you.

How sad.

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 7:50 pm

if one does not know an answer this would not mean that there is no answer.
So what actually is your intention to post this
I think your question has been answered many times. The simple answer is "No, there is no readily available library to do your homework for you". You just don't want to accept that answer and prefer to attack people who are trying to help you.
- another attempt to lecture and to bash me?
Let people answer who may know an answer, or walk on!

So a lib to #include plus this sort of

Code: Select all

PlayTone(440, 250);
is what I am still looking for, to work out of the box must already be provided.
- Tim

User avatar
kusti8
Posts: 3439
Joined: Sat Dec 21, 2013 5:29 pm
Location: USA

Re: Code to generate real-time sound

Tue Oct 04, 2016 7:55 pm

Why is it a must that it must be out of the box?
There are 10 types of people: those who understand binary and those who don't.

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 7:58 pm

please don't try to discuss with me about what I want or not, just accept what I am looking for.
If you know what I am looking for, show me, or please walk on.

So I am still looking for a lib to #include plus this sort of

Code: Select all

PlayTone(440, 250);
to work out of the box and which must already be provided.
- Tim

User avatar
rpdom
Posts: 17196
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Code to generate real-time sound

Tue Oct 04, 2016 8:11 pm

tito-t wrote:please don't try to discuss with me about what I want or not, just accept what I am looking for.
If you know what I am looking for, show me, or please walk on.

So I am still looking for a lib to #include plus this sort of

Code: Select all

PlayTone(440, 250);
to work out of the box and which must already be provided.
You keep repeating yourself. Are you a bot? Why do you think that this must be provided? Because you say it is so?
Please take your fingers out of your arears and listen to what people are telling you. They are trying to help you even though you reject it because it doesn't seem to fit into your world view.

tito-t
Posts: 298
Joined: Thu Jan 07, 2016 5:14 pm

Re: Code to generate real-time sound

Tue Oct 04, 2016 8:25 pm

what in the world gives you the right to repeatedly impugn my question? Are you a bot?
I ask my question because this is my question, period.
If you know the answer, you are welcome, if not, please shut off and walk along - as I already wrote:
I don't want to discuss about my wish, I stated that I need this function and I think I would not be the first one who is looking for sth like this - see above, the thread opening post of the original poster.
...
So if no one knows a solution to my question, ok, he is not forced to answer and - above all - not asked to bash or to lecture me (as it often seems to be a common practice of some forum's members).
But any really helpful hints to such libs are very much appreciated. Perhaps someone is eventually supposed to know what I am searching for.
I repeat my question simply because some (actually always the same) people try to torpedo and shred my question which was about
a lib to #include plus this sort of

Code: Select all

PlayTone(440, 250);
to work out of the box and which must already be provided.
- Tim

User avatar
rpdom
Posts: 17196
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Code to generate real-time sound

Tue Oct 04, 2016 8:31 pm

tito-t wrote:I repeat my question simply because some (actually always the same) people try to torpedo and shred my question
Or is that to improve your search engine ranking?
The question has been asked.
Wait for answers that make you happy.
Don't keep spamming the same thing over and over again because it will reduce your chance of an answer.

Just trying to help.

Return to “C/C++”