first commit
This commit is contained in:
commit
125936dfa0
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
*.wav
|
||||
/conv
|
10
Makefile
Normal file
10
Makefile
Normal file
|
@ -0,0 +1,10 @@
|
|||
CFLAGS= -Wfatal-errors $(shell pkgconf --cflags portaudio-2.0)
|
||||
LDFLAGS= -s $(shell pkgconf --libs portaudio-2.0)
|
||||
|
||||
all: conv
|
||||
conv: main.o
|
||||
$(CC) $^ -o $@ $(LDFLAGS)
|
||||
%.o: %.c
|
||||
$(CC) -c $^ -o $@ $(CFLAGS)
|
||||
clean:
|
||||
$(RM) conv *.o
|
143
main.c
Normal file
143
main.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
#include<portaudio.h>
|
||||
#include<stdio.h>
|
||||
#include<stdlib.h>
|
||||
#include<math.h>
|
||||
#include<stdint.h>
|
||||
#include<unistd.h>
|
||||
#include<fcntl.h>
|
||||
#include<string.h>
|
||||
|
||||
// Open .WAV file, read into buffer
|
||||
// assuming samplerate, bitdepth, and
|
||||
// channels
|
||||
void op(const char*fn,float*buf,int len)
|
||||
{
|
||||
int fd;
|
||||
int16_t tmpbuf[len];
|
||||
if(!fn||!buf||!len)return;
|
||||
|
||||
fd=open(fn,O_RDONLY);
|
||||
if(fd<0)
|
||||
{
|
||||
write(1,"fail\n",5);
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip WAVE header (assume 44.1kHz
|
||||
// samplerate, mono channels, and 16bit
|
||||
lseek(fd,40,SEEK_SET);
|
||||
|
||||
// Read file into buffer and convert from
|
||||
// int16_t to float
|
||||
read(fd,tmpbuf,len*sizeof(int16_t));
|
||||
for(int i=0;i<len;++i)
|
||||
buf[i]=((float)tmpbuf[i])/(float)INT16_MAX;
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
// Low-pass convolving filter
|
||||
void lp(float*cur,float*prev,float*next,int len,int winsz)
|
||||
{
|
||||
if(!cur||!prev||!next||!len||!winsz)return;
|
||||
for(int i=0,k;i<len;++i)
|
||||
{
|
||||
float sum=0;
|
||||
k=i-winsz/2;
|
||||
for(int j=0;j<winsz;++j,++k)
|
||||
{
|
||||
if(k<0)
|
||||
sum+=prev[k+len];
|
||||
else if(k>=len)
|
||||
sum+=next[k%len];
|
||||
else
|
||||
sum+=cur[k];
|
||||
}
|
||||
cur[i]=sum/winsz;
|
||||
}
|
||||
}
|
||||
|
||||
// Sine oscillator
|
||||
void sn(float*d,int len,int cycle,int*offset)
|
||||
{
|
||||
for(int j=0,cycle=44100/440;j<len;++j,*offset=(*offset+1)%cycle)
|
||||
d[j]=sin(2.0*M_PI*((float)*offset)/cycle)*0.25;
|
||||
}
|
||||
|
||||
// Saw-tooth oscillator
|
||||
void sw(float*d,int len,int cycle,int*offset)
|
||||
{
|
||||
*offset%=cycle;
|
||||
for(int j=0,cycle=44100/440;j<len;++j,*offset=(*offset+1)%cycle)
|
||||
d[j]=((float)*offset)/cycle*0.25;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define swapbuffers() do{float*tmp=prev;prev=cur;cur=next;next=tmp;}while(0)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
PaStream*pa;
|
||||
const int len=1024;
|
||||
float buffer1[len];
|
||||
float buffer2[len];
|
||||
float buffer3[len];
|
||||
float wave[44100];
|
||||
float*cur=buffer2,*next=buffer3,*prev=buffer1;
|
||||
int envsize=400;
|
||||
int offset=0;
|
||||
int wave_or_osc=0;
|
||||
|
||||
if(envsize>len)envsize=len;
|
||||
|
||||
// Init portaudio
|
||||
Pa_Initialize();
|
||||
Pa_OpenDefaultStream(&pa,0,1,paFloat32,44100,len,NULL,NULL);
|
||||
Pa_StartStream(pa);
|
||||
|
||||
// Read wave file into buffer
|
||||
op("w.wav",wave,44100);
|
||||
|
||||
// Generate initial buffer
|
||||
if(wave_or_osc==0)
|
||||
sw(next,len,44100/440,&offset);
|
||||
else
|
||||
{
|
||||
memcpy(next,wave+offset,len*sizeof(float));
|
||||
offset+=len;
|
||||
}
|
||||
|
||||
// Play dynamic audio
|
||||
for(int i=0,last=44100/len/2;i<last;++i)
|
||||
{
|
||||
swapbuffers();
|
||||
|
||||
// Oscillator
|
||||
if(wave_or_osc==0)
|
||||
sw(next,len,44100/440,&offset);
|
||||
else
|
||||
{
|
||||
memcpy(next,wave+offset,len*sizeof(float));
|
||||
offset+=len;
|
||||
}
|
||||
|
||||
// Filter
|
||||
lp(cur,prev,next,len,44100/1000);
|
||||
|
||||
// Amplitude envelope
|
||||
if(i==0)
|
||||
for(int j=0;j<envsize;++j)
|
||||
cur[j]*=((float)j)/envsize;
|
||||
else if(i==last-1)
|
||||
for(int j=0;j<envsize;++j)
|
||||
cur[len-j]*=((float)j)/envsize;
|
||||
|
||||
Pa_WriteStream(pa,cur,len);
|
||||
}
|
||||
Pa_Sleep(800);
|
||||
|
||||
// Quit
|
||||
Pa_CloseStream(pa);
|
||||
Pa_Terminate();
|
||||
}
|
Loading…
Reference in New Issue
Block a user