Created
June 9, 2016 21:04
-
-
Save yne/e4adf578a14953c4547d078406d575d4 to your computer and use it in GitHub Desktop.
Play argv wavs using ALSA
This file contains 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 <alloca.h> /*needed (yet not included) by asoundlib in c99*/ | |
#include <alsa/asoundlib.h>/* build with -lasound */ | |
#include <stdint.h> | |
#define $(x) if ((x) < 0) { fprintf(stderr, "Error:%s", # x); return -1; } | |
#define MIN(A, B) ((A) < (B) ? (A) : (B)) | |
typedef struct { | |
char RIFF[4]; | |
uint32_t ChunkSize; | |
char WAVE[4]; | |
char fmt[4]; | |
uint32_t Subchunk1Size; | |
int16_t AudioFormat; | |
int16_t NumOfChannels; | |
uint32_t SamplesPerSec; | |
uint32_t bytesPerSec; | |
int16_t blockAlign; | |
int16_t bitsPerSample; | |
char Subchunk2ID[4]; | |
uint32_t Subchunk2Size; | |
char data[1]; | |
} wavHeader; | |
typedef struct { | |
void* data; | |
wavHeader*wav_hdr; | |
size_t wav_size; | |
char* wav_data; | |
}sound_file_t; | |
sound_file_t wavs[256]; | |
size_t wavs_loaded = 0; | |
void load_wavs(char** paths, size_t total) | |
{ | |
for (int i = 0; i < total; i++) { | |
sound_file_t*wav = &wavs[wavs_loaded]; | |
FILE *file = fopen(paths[i], "rb"); | |
if (file == NULL) | |
continue; | |
fseek(file, 0, SEEK_END); | |
wav->wav_size = ftell(file); | |
fseek(file, 0, SEEK_SET); | |
wav->data = malloc(wav->wav_size); | |
if (wav->data != NULL) { | |
fread(wav->data, 1, wav->wav_size, file); | |
wav->wav_hdr = wav->data; | |
wav->wav_data = ((char*)wav->data) + sizeof(wavHeader) + wav->wav_hdr->Subchunk2Size; | |
wav->wav_size = wav->wav_size + sizeof(wavHeader) + wav->wav_hdr->Subchunk2Size; | |
wavs_loaded++; | |
} | |
fclose(file); | |
} | |
} | |
void unload_wavs() | |
{ | |
for (int i = 0; i < wavs_loaded; i++) | |
free(wavs[i].data); | |
} | |
int main(int argc, char**argv) | |
{ | |
int i; | |
load_wavs(argv + 1, argc - 1); | |
snd_pcm_t *handle; | |
$(snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)); | |
snd_pcm_hw_params_t *params; | |
snd_pcm_hw_params_alloca(¶ms); | |
snd_pcm_hw_params_any(handle, params); | |
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); | |
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); | |
snd_pcm_hw_params_set_channels(handle, params, wavs[0].wav_hdr->NumOfChannels); | |
snd_pcm_hw_params_set_rate_near(handle, params, &wavs[0].wav_hdr->SamplesPerSec, &i); | |
$(snd_pcm_hw_params(handle, params)); | |
// snd_pcm_prepare(handle); | |
for (int wav = 0; wav < wavs_loaded; wav) { | |
char*wav_data = wavs[wav].wav_data; | |
snd_pcm_uframes_t frames_size = wavs[wav].wav_hdr->NumOfChannels * sizeof(uint16_t); | |
int frames_remain = wavs[wav].wav_size / frames_size; | |
unsigned frames_step = 1024; | |
while (frames_remain > 0) { | |
snd_pcm_writei(handle, wav_data, MIN(frames_remain, frames_step)); | |
frames_remain -= frames_step; | |
wav_data += frames_step * frames_size; | |
} | |
} | |
snd_pcm_drain(handle); | |
snd_pcm_close(handle); | |
unload_wavs(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment