Last active
May 26, 2020 16:58
-
-
Save johnroper100/b87641f5609dbb49bc3c1121b1f4daf1 to your computer and use it in GitHub Desktop.
Test code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <vector> | |
#include <iostream> | |
#include <string> | |
#include "portaudio.h" | |
#include <sndfile.hh> | |
#include <cstring> | |
#include <thread> | |
#include <chrono> | |
using namespace std::chrono; | |
#define NUMCHANNELS (2) | |
#define SAMPLE_RATE (48000) | |
#define FRAMES_PER_BUFFER (512) | |
class Sound | |
{ | |
public: | |
std::string fname; | |
int midnote, channel, rate, loop, nframes; | |
float *data; | |
void init(std::string filename, bool release, int midinote); | |
}; | |
void Sound::init(std::string filename, bool release, int midinote) | |
{ | |
SNDFILE *wf; | |
SF_INFO inFileInfo; | |
channel = 0; | |
wf = sf_open(filename.c_str(), SFM_READ, &inFileInfo); | |
SF_INSTRUMENT inst; | |
sf_command(wf, SFC_GET_INSTRUMENT, &inst, sizeof(inst)); | |
if (release == false && inst.loop_count > 0) | |
{ | |
loop = inst.loops[0].start; | |
nframes = inst.loops[0].end; | |
} | |
else | |
{ | |
loop = -1; | |
nframes = inFileInfo.frames; | |
} | |
data = (float *)malloc((nframes * 2) * sizeof(float)); | |
sf_read_float(wf, data, nframes * 2); | |
rate = inFileInfo.samplerate; | |
sf_close(wf); | |
}; | |
class PlayingSound | |
{ | |
public: | |
Sound sound; | |
int pos, fadeoutpos, fadeinpos, note; | |
bool isfadeout, isfadein; | |
double volMult, pitchMult; | |
void init(Sound s, int midinote); | |
void fadeout(); | |
void fadein(); | |
}; | |
void PlayingSound::init(Sound s, int midinote) | |
{ | |
sound = s; | |
pos = 0; | |
fadeoutpos = 0; | |
fadeinpos = 0; | |
isfadein = false; | |
isfadeout = false; | |
note = midinote; | |
volMult = 1.0; | |
pitchMult = 1.0; | |
}; | |
void PlayingSound::fadeout() | |
{ | |
isfadeout = true; | |
}; | |
void PlayingSound::fadein() | |
{ | |
isfadein = true; | |
}; | |
static int patestCallback(const void *inputBuffer, void *outputBuffer, | |
unsigned long framesPerBuffer, | |
const PaStreamCallbackTimeInfo *timeInfo, | |
PaStreamCallbackFlags statusFlags, void *userData) | |
{ | |
//auto start = high_resolution_clock::now(); | |
(void)timeInfo; /* Prevent unused variable warnings. */ | |
(void)statusFlags; | |
(void)inputBuffer; | |
float *out = (float *)outputBuffer; | |
memset(out, 0, sizeof(float) * framesPerBuffer * NUMCHANNELS); | |
std::vector<PlayingSound>* playingsounds = (std::vector<PlayingSound> *)userData; | |
int sizeLength = playingsounds->size(); | |
int kk; | |
int ii; | |
int pos; | |
int k; | |
int nframes, loop, channel; | |
float *data; | |
for (int jj = 0; jj < sizeLength; jj++) | |
{ | |
PlayingSound &snd = playingsounds[0][jj]; | |
kk = 0; | |
ii = 0; | |
pos = snd.pos; | |
nframes = snd.sound.nframes; | |
loop = snd.sound.loop; | |
channel = snd.sound.channel; | |
data = snd.sound.data; | |
for (int i = 0; i < framesPerBuffer; i++) | |
{ | |
k = pos + ii; | |
ii += 1; | |
if (k > nframes - 2) | |
{ | |
pos = loop + 1; | |
snd.pos = pos; | |
ii = 0; | |
k = pos; | |
}; | |
out[NUMCHANNELS * i + channel] += data[2 * k]; | |
out[NUMCHANNELS * i + channel + 1] += data[2 * k + 1]; | |
}; | |
snd.pos += ii; | |
}; | |
//auto stop = high_resolution_clock::now(); | |
//auto duration = duration_cast<microseconds>(stop-start); | |
//std::cout << duration.count() << std::endl; | |
return paContinue; | |
} | |
void foo(void *userData) | |
{ | |
std::vector<PlayingSound> *playingSounds = (std::vector<PlayingSound> *)userData; | |
Sound test; | |
test.init("test.wav", false, 36); | |
PlayingSound test1; | |
test1.init(test, 36); | |
playingSounds->push_back(test1); | |
Sound test2; | |
test2.init("test2.wav", false, 36); | |
for (int i = 0; i < 10000; i++) | |
{ | |
PlayingSound test3; | |
test3.init(test2, 36); | |
playingSounds->push_back(test3); | |
}; | |
} | |
int main(void); | |
int main(void) | |
{ | |
PaStreamParameters outputParameters; | |
PaStream *stream; | |
PaError err; | |
std::vector<PlayingSound> playingSounds; | |
std::thread thread_obj(foo, &playingSounds); | |
thread_obj.join(); | |
err = Pa_Initialize(); | |
if (err != paNoError) | |
goto error; | |
outputParameters.device = Pa_GetDefaultOutputDevice(); | |
if (outputParameters.device == paNoDevice) | |
{ | |
fprintf(stderr, "Error: No default output device.\n"); | |
goto error; | |
} | |
outputParameters.channelCount = NUMCHANNELS; | |
outputParameters.sampleFormat = paFloat32; | |
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency; | |
outputParameters.hostApiSpecificStreamInfo = NULL; | |
err = Pa_OpenStream( | |
&stream, | |
NULL, | |
&outputParameters, | |
SAMPLE_RATE, | |
FRAMES_PER_BUFFER, | |
paClipOff, | |
patestCallback, | |
&playingSounds); | |
if (err != paNoError) | |
goto error; | |
err = Pa_StartStream(stream); | |
if (err != paNoError) | |
goto error; | |
while (1) | |
{ | |
Pa_Sleep(1000); | |
} | |
err = Pa_StopStream(stream); | |
if (err != paNoError) | |
goto error; | |
err = Pa_CloseStream(stream); | |
if (err != paNoError) | |
goto error; | |
Pa_Terminate(); | |
return err; | |
error: | |
Pa_Terminate(); | |
fprintf(stderr, "An error occured while using the portaudio stream\n"); | |
fprintf(stderr, "Error number: %d\n", err); | |
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err)); | |
return err; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment