fix audio playback bug
This commit is contained in:
parent
ecdbc8c570
commit
8649141cbb
24
audio.c
24
audio.c
|
@ -12,7 +12,7 @@
|
|||
#include"audio.h"
|
||||
|
||||
/*******
|
||||
* Allocate data, initialize struct
|
||||
* Create new Audio struct
|
||||
*******/
|
||||
Audio aud_new(size_t samplerate,size_t nsamples,size_t channels)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ Audio aud_new(size_t samplerate,size_t nsamples,size_t channels)
|
|||
}
|
||||
|
||||
/*******
|
||||
* Free allocated data
|
||||
* Free Audio struct resources
|
||||
*******/
|
||||
void aud_free(Audio*aud)
|
||||
{
|
||||
|
@ -79,6 +79,7 @@ void aud_tri(Audio*aud,double freq,size_t mode)
|
|||
for(size_t i=0;i<aud->nsamples;++i)
|
||||
{
|
||||
/* for(size_t ch=0;ch<aud->channels;++ch,++i) */
|
||||
//aud->data[i]=sin(i);
|
||||
uint16_t sample=(i%(int)(aud->samplerate/freq))*7;
|
||||
if(mode==GEN)
|
||||
aud->data[i]=sample;
|
||||
|
@ -87,23 +88,6 @@ void aud_tri(Audio*aud,double freq,size_t mode)
|
|||
}
|
||||
}
|
||||
|
||||
/*******
|
||||
* Sine waveform generator
|
||||
*******/
|
||||
void aud_sine(Audio*aud,double freq,size_t mode)
|
||||
{
|
||||
if(!aud->data||!aud->nsamples||!aud->samplerate||!aud->channels)return;
|
||||
for(size_t i=0;i<aud->nsamples;++i)
|
||||
{
|
||||
/* for(size_t ch=0;ch<aud->channels;++ch,++i) */
|
||||
uint16_t sample=sin((2*PI)/(aud->samplerate/freq)*i)*8000;
|
||||
if(mode==GEN)
|
||||
aud->data[i]=sample;
|
||||
else if(mode==ADD)
|
||||
aud->data[i]=(aud->data[i]+sample)/2;
|
||||
}
|
||||
}
|
||||
|
||||
/*******
|
||||
* Zero all data
|
||||
*******/
|
||||
|
@ -114,7 +98,7 @@ void aud_zero(Audio*aud)
|
|||
}
|
||||
|
||||
/*******
|
||||
* Naïve amplitude envelope to smooth popping
|
||||
* Naïve amplitude envelope
|
||||
*******/
|
||||
void aud_env(Audio*aud)
|
||||
{
|
||||
|
|
35
audio.h
35
audio.h
|
@ -12,24 +12,6 @@
|
|||
#include<time.h>
|
||||
#include<unistd.h>
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.141592653589793L
|
||||
#endif
|
||||
#define SEMITONE_CONSTANT 1.0594630943592953L // pow(2,1/12.0)
|
||||
|
||||
// Raise by one semitone
|
||||
#define raisesemitone(freq,nsemitones) ((freq)*pow(SEMITONE_CONSTANT,(nsemitones)))
|
||||
|
||||
// Macro to generate chord
|
||||
// composed of semitone intervals
|
||||
#define makechord(aud,freq,...) do{int _l[]={__VA_ARGS__};aud_tri(aud,(freq),GEN);for(size_t i=0;i<sizeof(_l)/sizeof(int);++i)aud_tri(aud,raisesemitone((freq),_l[i]),ADD);}while(0)
|
||||
|
||||
enum{GEN,ADD};
|
||||
|
||||
/*******
|
||||
* Type to store audio
|
||||
* data information
|
||||
*******/
|
||||
typedef struct Audio
|
||||
{
|
||||
size_t samplerate;
|
||||
|
@ -39,10 +21,21 @@ typedef struct Audio
|
|||
} Audio;
|
||||
|
||||
Audio aud_new(size_t samplerate,size_t nsamples,size_t channels);
|
||||
void aud_avg(Audio*aud,size_t blocksize);
|
||||
void aud_env(Audio*aud);
|
||||
void aud_free(Audio*aud);
|
||||
|
||||
// Audio data manipulation
|
||||
#define SEMITONE_CONSTANT 1.0594630943592953 // pow(2,1/12.0)
|
||||
#define raisesemitone(freq,nsemitones) ((freq)*pow(SEMITONE_CONSTANT,(nsemitones)))
|
||||
|
||||
// Generate chord in Audio struct
|
||||
// starting at base freq, and using
|
||||
// all specified semitone intervals
|
||||
#define makechord(aud,freq,...) do{double _f=(freq);int _l[]={__VA_ARGS__};aud_tri((aud),_f,GEN);for(size_t i=0;i<sizeof(_l)/sizeof(int);++i)aud_tri((aud),raisesemitone(_f,_l[i]),ADD);}while(0)
|
||||
|
||||
enum{GEN,ADD};
|
||||
|
||||
void aud_avg(Audio*aud,size_t blocksize);
|
||||
void aud_rnd(Audio*aud,size_t mode);
|
||||
void aud_sine(Audio*aud,double freq,size_t mode);
|
||||
void aud_tri(Audio*aud,double freq,size_t mode);
|
||||
void aud_zero(Audio*aud);
|
||||
void aud_env(Audio*aud);
|
||||
|
|
45
main.c
45
main.c
|
@ -18,14 +18,16 @@
|
|||
|
||||
#define USAGE "chord [CHORDs]\n"\
|
||||
"\tCHORD\t[a-g][#b]?[0-9][m]?\n"
|
||||
#define chord(aud,f,...) makechord((aud),(nametofreq(f)),__VA_ARGS__)
|
||||
#define M7(aud,f) chord(aud,f,4,7,11) // major 7
|
||||
#define f7(aud,f) chord(aud,f,4,7,10) // flat 7
|
||||
#define m7(aud,f) chord(aud,f,3,7,10) // minor 7
|
||||
#define d7(aud,f) chord(aud,f,3,6,10) // diminished 7
|
||||
|
||||
double nametofreq(const char*name);
|
||||
void cleanup(int sig);
|
||||
// Chord generator macros
|
||||
#define chord(aud,f,...) makechord(aud,nametofreq(f),__VA_ARGS__)
|
||||
#define M7(aud,f) chord(aud,f,4,7,11)
|
||||
#define f7(aud,f) chord(aud,f,4,7,10)
|
||||
#define m7(aud,f) chord(aud,f,3,7,10)
|
||||
#define d7(aud,f) chord(aud,f,3,6,10)
|
||||
|
||||
static double nametofreq(const char*name);
|
||||
static void cleanup(int sig);
|
||||
|
||||
static Audio aud=(Audio){0};
|
||||
static PaStream*pa=NULL;
|
||||
|
@ -53,21 +55,22 @@ int main(int argc,char**argv)
|
|||
// Macro to play audio
|
||||
#define play() do{Pa_WriteStream(pa,aud.data,aud.nsamples);usleep((((float)aud.nsamples)/aud.samplerate)*1000000);}while(0)
|
||||
|
||||
// Play pre-written chords
|
||||
// Play pre-designed chord scale
|
||||
if(argc<2)
|
||||
{
|
||||
// Play chord scale
|
||||
chord(&aud,"a4",4,7,11,14);aud_env(&aud);play();
|
||||
chord(&aud,"g#4",3,6,9,13);aud_env(&aud);play();
|
||||
chord(&aud,"f#4",3,7,10,14);aud_env(&aud);play();
|
||||
chord(&aud,"e4",4,7,10,14);aud_env(&aud);play();
|
||||
chord(&aud,"d4",4,7,11,14);aud_env(&aud);play();
|
||||
chord(&aud,"c#4",3,7,10,13);aud_env(&aud);play();
|
||||
chord(&aud,"b3",3,7,10,14);aud_env(&aud);play();
|
||||
chord(&aud,"a3",4,7,11,14);aud_env(&aud);play();
|
||||
chord(&aud, "a4",4,7,11,14);aud_env(&aud);play();
|
||||
chord(&aud, "g#4",3,6,9,13);aud_env(&aud);play();
|
||||
chord(&aud, "f#4",3,7,10,14);aud_env(&aud);play();
|
||||
chord(&aud, "e4",4,7,10,14);aud_env(&aud);play();
|
||||
chord(&aud, "d4",4,7,11,14);aud_env(&aud);play();
|
||||
chord(&aud, "c#4",3,7,10,13);aud_env(&aud);play();
|
||||
chord(&aud, "b3",3,7,10,14);aud_env(&aud);play();
|
||||
chord(&aud, "a3",4,7,11,14);aud_env(&aud);play();
|
||||
//Pa_Sleep((((float)aud.nsamples)/aud.samplerate)*8);
|
||||
}
|
||||
|
||||
// Play command-line supplied chords
|
||||
// Play command-line supplied chord names
|
||||
else
|
||||
{
|
||||
for(size_t i=1;i<(size_t)argc;++i)
|
||||
|
@ -101,7 +104,7 @@ int main(int argc,char**argv)
|
|||
/*******
|
||||
* Convert note name into frequency
|
||||
*******/
|
||||
double nametofreq(const char*name)
|
||||
static double nametofreq(const char*name)
|
||||
{
|
||||
char letter='a';
|
||||
double a0=27.5;
|
||||
|
@ -134,12 +137,14 @@ double nametofreq(const char*name)
|
|||
}
|
||||
|
||||
/*******
|
||||
* Free resources
|
||||
* Free resources and quit
|
||||
*******/
|
||||
void cleanup(int sig)
|
||||
static void cleanup(int sig)
|
||||
{
|
||||
if(sig==SIGINT)
|
||||
puts("exiting due to SIGINT");
|
||||
/* else */
|
||||
/* puts("bye"); */
|
||||
Pa_AbortStream(pa);
|
||||
Pa_CloseStream(pa);
|
||||
Pa_Terminate();
|
||||
|
|
Loading…
Reference in New Issue
Block a user