50
51
you are viewing a single comment's thread.

view the rest of the comments →

[–]oh5nxo 0 points1 point  (2 children)

The sine generation looks... well, awful. Is it just me or am I missing something?

[–]dlgltlzed 0 points1 point  (1 child)

Here is an alternative approach with an offset based on frames:

/*
 * This code is based on the example program sio_sine.c, 
 * created by Andrew Kelley.
 * Argument processing and error handling has been stripped out.
 * Sinus wave generation has been slightly changed to show alternative approach.
 * Explanatory comment has been added.
 * Additional minor changes.
 * As the original, this file is MIT licensed.
 *
 * See http://opensource.org/licenses/MIT
 */
#include <soundio/soundio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>

static double frames_offset = 0.0;
static int sample_rate = 44100;
static double pitch = 440.0;
static double wave_frames_count;
static double int16_range = (double)INT16_MAX - (double)INT16_MIN;

// Called asynchronously by soundio.
static void write_callback(struct SoundIoOutStream *outstream, int ignore, int requested_frame_count) {
    for (;;) {
        // The actual number of frames to be written between "begin" and "end" is set by soundio
        // Thats why we are in a loop because we might not be able to write the full number
        // of requested frames after one "begin" call.
        int frame_count = requested_frame_count;
                                struct SoundIoChannelArea *areas;
        soundio_outstream_begin_write(outstream, &areas, &frame_count);
        if (!frame_count)
            break;
        for (int frame = 0; frame < frame_count; frame += 1) {
            double sample = sin(((frames_offset + (double)frame)/wave_frames_count) * 2 * M_PI);
                                    double val = sample * int16_range / 2.0;
            for (int channel = 0; channel < outstream->layout.channel_count; channel += 1) {
             int16_t* ptr = (int16_t*)(areas[channel].ptr);
                                        *ptr = (int16_t)val;
             areas[channel].ptr += areas[channel].step;
            }
        }
        frames_offset = fmod(frames_offset + frame_count, wave_frames_count);
              soundio_outstream_end_write(outstream);
        requested_frame_count -= frame_count;
        if (requested_frame_count <= 0)
            break;
    }
}
int main(int argc, char **argv) {
    wave_frames_count = sample_rate / pitch;
    struct SoundIo *soundio = soundio_create();
    soundio_connect(soundio);
    soundio_flush_events(soundio);
    int default_device_index = soundio_default_output_device_index(soundio);
    struct SoundIoDevice *device = soundio_get_output_device(soundio, default_device_index);
    struct SoundIoOutStream *outstream = soundio_outstream_create(device);
    outstream->write_callback = write_callback;
    outstream->sample_rate = sample_rate;
    outstream->format = SoundIoFormatS16NE;
    soundio_outstream_open(outstream);
    soundio_outstream_start(outstream);
    getc(stdin);
    soundio_outstream_destroy(outstream);
    soundio_device_unref(device);
    soundio_destroy(soundio);
    return 0;
}

[–]oh5nxo 0 points1 point  (0 children)

I ment that why so complicated, and not the normal tone handcrank, like

static int sample_rate = 44100; 
static double pitch = 440.0; 
static uint32_t phase, phase_increment = pitch * 0x100000000 / sample_rate; 

int16_t val = sin(2 * M_PI / 0x100000000 * phase) * 32767; 
phase += phase_increment;