Skip to content

Instantly share code, notes, and snippets.

@seece
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save seece/8831890 to your computer and use it in GitHub Desktop.
Save seece/8831890 to your computer and use it in GitHub Desktop.
Tracker module playback using PortAudio and DUMB.
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <stdbool.h>
#include <portaudio.h>
#include "dumb.h"
#include "audio.h"
#define BUFFERSIZE (2048L)
#define SAMPLE_RATE (44100)
static PaStream* stream = NULL;
static DUH_SIGRENDERER* renderer = NULL;
static enum {STATE_PAUSED, STATE_PLAYING} player_state;
// just a test
int temp_userdata = 42;
void die(const char* str)
{
fprintf(stderr, "%s\n", str);
exit(1);
}
void pa_error(PaError err)
{
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 ) );
die("Fatal error");
}
static int audioCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
signed short* out = (signed short*)outputBuffer;
// fill the buffer with silence if no renderer has been created yet
if (!renderer || (player_state == STATE_PAUSED)) {
for (int i=0;i<BUFFERSIZE*2;i++) {
out[i] = 0;
}
return paContinue;
}
long result = duh_render(renderer, 16, 0, 1.0, 65536.0f/SAMPLE_RATE, BUFFERSIZE, out);
//PlaybackInfo* info = (PlaybackInfo*)userData;
return paContinue;
}
bool init_portaudio()
{
PaError err;
PaStreamParameters outputParameters;
err = Pa_Initialize();
if (err!=paNoError) return true;
printf("Using portaudio v%d\n", Pa_GetVersion());
int samplesize = Pa_GetSampleSize(paInt16);
assert(samplesize == 2); // we like 16-bit audio
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
die("Error: No default output device.");
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paInt16; /* 16 bit signed integer output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
(double)SAMPLE_RATE,
BUFFERSIZE,
0,
audioCallback,
&temp_userdata);
if (err != paNoError) pa_error(err);
return false;
}
void audio_init()
{
player_state = STATE_PAUSED;
PaError err;
puts("dumb init");
dumb_register_stdfiles();
puts("portaudio init");
if (init_portaudio())
die("Couldn't initialize portaudio!!");
err = Pa_StartStream(stream);
if (err != paNoError) pa_error(err);
player_state = STATE_PLAYING;
}
void audio_close()
{
PaError err;
err = Pa_StopStream(stream);
if (err != paNoError) pa_error(err);
duh_end_sigrenderer(renderer);
renderer = NULL;
dumb_exit();
err = Pa_CloseStream(stream);
if (err != paNoError) pa_error(err);
Pa_Terminate();
}
void audio_play_song(DUH* song)
{
if (renderer)
duh_end_sigrenderer(renderer);
renderer = duh_start_sigrenderer(song, 0, 2, 0);
}
void audio_pause_song(DUH* song)
{
player_state = STATE_PAUSED;
}
void audio_continue_song(DUH* song)
{
player_state = STATE_PLAYING;
}
#pragma once
#include "dumb.h"
void audio_init();
void audio_close();
void audio_play_song(DUH* song);
void audio_pause_song(DUH* song);
void audio_continue_song(DUH* song);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment