mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-27 10:50:23 -04:00
The commands and values were not very good names to what the byte sequences actually are: opcodes and their operands. In many other places, we were already calling the byte in the Command stream as Opcode, so a logical name for a sequence of these is Opcodes. Values is such a generic name that it's not immediately clear that this sequence is related to the opcodes. Operands is not perfect but clearly suggests that this sequence is related to the Opcodes.
143 lines
4.4 KiB
C
143 lines
4.4 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <sointu.h>
|
|
|
|
#define BPM 100
|
|
#define SAMPLE_RATE 44100
|
|
#define LENGTH_IN_ROWS 16
|
|
#define SAMPLES_PER_ROW SAMPLE_RATE * 4 * 60 / (BPM * 16)
|
|
const int su_max_samples = SAMPLES_PER_ROW * LENGTH_IN_ROWS;
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
Synth *synth;
|
|
float *buffer;
|
|
const unsigned char opcodes[] = {SU_ENVELOPE_ID, // MONO
|
|
SU_ENVELOPE_ID, // MONO
|
|
SU_OUT_ID + 1, // STEREO
|
|
SU_ADVANCE_ID}; // MONO
|
|
const unsigned char operands[] = {64, 64, 64, 80, 128, // envelope 1
|
|
95, 64, 64, 80, 128, // envelope 2
|
|
128};
|
|
int errcode;
|
|
int time;
|
|
int samples;
|
|
int totalrendered;
|
|
int retval;
|
|
// initialize Synth
|
|
synth = (Synth *)malloc(sizeof(Synth));
|
|
memset(synth, 0, sizeof(Synth));
|
|
memcpy(synth->Opcodes, opcodes, sizeof(opcodes));
|
|
memcpy(synth->Operands, operands, sizeof(operands));
|
|
synth->NumVoices = 1;
|
|
synth->Polyphony = 0;
|
|
synth->RandSeed = 1;
|
|
// initialize Buffer
|
|
buffer = (float *)malloc(2 * sizeof(float) * su_max_samples);
|
|
// triger first voice
|
|
synth->SynthWrk.Voices[0].Note = 64;
|
|
synth->SynthWrk.Voices[0].Sustain = 1;
|
|
totalrendered = 0;
|
|
// First check that when we render using su_render with 0 time
|
|
// we get nothing done
|
|
samples = su_max_samples;
|
|
time = 0;
|
|
errcode = su_render(synth, buffer, &samples, &time);
|
|
if (errcode != 0)
|
|
goto fail;
|
|
if (samples > 0)
|
|
{
|
|
printf("su_render rendered samples, despite it should not\n");
|
|
goto fail;
|
|
}
|
|
if (time > 0)
|
|
{
|
|
printf("su_render advanced time, despite it should not\n");
|
|
goto fail;
|
|
}
|
|
// Then check that when we render using su_render with 0 samples,
|
|
// we get nothing done
|
|
samples = 0;
|
|
time = INT32_MAX;
|
|
errcode = su_render(synth, buffer, &samples, &time);
|
|
if (errcode != 0)
|
|
goto fail;
|
|
if (samples > 0)
|
|
{
|
|
printf("su_render rendered samples, despite it should not\n");
|
|
goto fail;
|
|
}
|
|
if (time > 0)
|
|
{
|
|
printf("su_render advanced time, despite it should not\n");
|
|
goto fail;
|
|
}
|
|
// Then check that each time we call render, only SAMPLES_PER_ROW
|
|
// number of samples are rendered
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
// Simulate "small buffers" i.e. render a buffer with 1 sample
|
|
// check that buffer full
|
|
samples = 1;
|
|
time = INT32_MAX;
|
|
errcode = su_render(synth, &buffer[totalrendered * 2], &samples, &time);
|
|
if (errcode != 0)
|
|
goto fail;
|
|
totalrendered += samples;
|
|
if (samples != 1)
|
|
{
|
|
printf("su_render should have return 1, as it should have believed buffer is full");
|
|
goto fail;
|
|
}
|
|
if (time != 1)
|
|
{
|
|
printf("su_render should have advanced the time also by one");
|
|
goto fail;
|
|
}
|
|
samples = SAMPLES_PER_ROW - 1;
|
|
time = INT32_MAX;
|
|
errcode = su_render(synth, &buffer[totalrendered * 2], &samples, &time);
|
|
if (errcode != 0)
|
|
goto fail;
|
|
totalrendered += samples;
|
|
if (samples != SAMPLES_PER_ROW - 1)
|
|
{
|
|
printf("su_render should have return SAMPLES_PER_ROW - 1, as it should have believed buffer is full");
|
|
goto fail;
|
|
}
|
|
if (time != SAMPLES_PER_ROW - 1)
|
|
{
|
|
printf("su_render should have advanced the time also by SAMPLES_PER_ROW - 1");
|
|
goto fail;
|
|
}
|
|
if (i == 8)
|
|
synth->SynthWrk.Voices[0].Sustain = 0;
|
|
}
|
|
if (totalrendered != su_max_samples)
|
|
{
|
|
printf("su_render should have rendered a total of su_max_samples");
|
|
goto fail;
|
|
}
|
|
retval = 0;
|
|
finish:
|
|
free(synth);
|
|
free(buffer);
|
|
return retval;
|
|
fail:
|
|
if (errcode > 0)
|
|
{
|
|
if ((errcode & 0xFF00) != 0)
|
|
printf("FPU stack was not empty on exit\n");
|
|
if ((errcode & 0x04) != 0)
|
|
printf("FPU zero divide\n");
|
|
if ((errcode & 0x01) != 0)
|
|
printf("FPU invalid operation\n");
|
|
if ((errcode & 0x40) != 0)
|
|
printf("FPU stack error\n");
|
|
}
|
|
retval = 1;
|
|
goto finish;
|
|
}
|