@Readme
# build mode
release : make
debug : make debug
# clean
make clean
@Makefile
SRC=alsa_playback.c
TARGET=playback
LIB=asound
target:
gcc -o${TARGET} ${SRC} -l${LIB}
debug:
gcc -DDEBUG -o${TARGET} ${SRC} -l${LIB}
clean:
rm -rf ${TARGET}
@ source
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <stdio.h>
#include <stdint.h>
#define BUF_SIZE (30*16000)
#define WR_SIZE (2048) // Why 2048 ???
void SetParameters(snd_pcm_t* handle, snd_pcm_hw_params_t* params);
void Playback(snd_pcm_t* handle, const char* sndfile);
int set_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params);
void get_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params);
int LoadSoundfile(const char* filename, uint8_t* buffer);
int main(int argc, char* argv[])
{
int err;
snd_pcm_t* handle;
snd_pcm_hw_params_t* params;
if (argc != 2)
{
fprintf(stderr, "Usage: ./playback [input_snd_file]\n");
exit(EXIT_FAILURE);
}
/* Open PCM device for playback */
if ((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
fprintf(stderr, "snd_pcm_open failed.\n");
exit(EXIT_FAILURE);
}
/* Allocate a hardware parameters object */
snd_pcm_hw_params_alloca(¶ms);
/* Setting Parameters */
SetParameters(handle, params);
/* Simple sound playback */
Playback(handle, argv[1]);
/* Close PCM device */
snd_pcm_close(handle);
return 0;
}
void Playback(snd_pcm_t* handle, const char* sndfile)
{
int err;
int16_t readBuffer[BUF_SIZE] = {0,};
int16_t* offset = readBuffer;
int fileSize=0, readSize=0;
/* Load a SoundFile */
fileSize = LoadSoundfile(sndfile, (uint8_t*)readBuffer);
/* Playback Loop until EOF */
while (offset - readBuffer <= fileSize)
{
int nRead = snd_pcm_writei(handle, offset, WR_SIZE);
#ifdef DEBUG
fprintf(stderr, "nRead(%d) => offsetSize(%d) / totalSize(%d)\n"
, nRead, offset - readBuffer, fileSize);
#endif
if (nRead == 0)
{
fprintf(stderr, "End of file on input\n");
}
else if (nRead == -EPIPE)
{
fprintf(stderr, "Underrun occurred.\n");
snd_pcm_prepare(handle);
nRead = 0;
}
else if (nRead < 0)
{
fprintf(stderr, "Read error.\n");
exit(EXIT_FAILURE);
}
usleep(10000);
offset += nRead;
}
}
int LoadSoundfile(const char* filename, uint8_t* buffer)
{
int nFileSize;
FILE* fp = fopen(filename, "r");
memset(buffer, 0, BUF_SIZE);
nFileSize = fread((int8_t*)buffer, sizeof(int16_t), BUF_SIZE, fp);
printf(" -> FileSize = %d\n", nFileSize);
return nFileSize;
}
void SetParameters(snd_pcm_t* handle, snd_pcm_hw_params_t* params)
{
int err;
/* Configure HW parameters */
if ((err = set_hw_params(handle, params)) < 0)
{
fprintf(stderr, "set_hw_params failed: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
#ifdef DEBUG
/* Display information about the PCM interface */
get_hw_params(handle, params);
#endif
}
int set_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params)
{
int err;
int channels;
int rate, direction, target;
snd_pcm_uframes_t period_size;
int periods, dir;
printf("*** Set pcm hw parameters ***\n");
/* Fill it in with default values */
if ((err = snd_pcm_hw_params_any(handle, params)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_any failed.\n");
return err;
}
/* Read/Write Interleaved mode */
if ((err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_access failed.\n");
return err;
}
/* Signed 16-bit little-endian format */
if ((err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_format failed.\n");
return err;
}
/* Mono channel, 1: mono, 2: stereo */
channels = 1;
if ((err = snd_pcm_hw_params_set_channels(handle, params, channels)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_channels failed.\n");
exit(EXIT_FAILURE);
}
/* 16 kbps sampling rate */
target = rate = 16000;
if ((err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_rate_near failed.\n");
return err;
}
/* 128 frames per period */
period_size = 128;
if ((err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, &dir)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_period_size_near failed.\n");
return err;
}
/* 16 periods per buffer */
periods = 16;
if ((err = snd_pcm_hw_params_set_periods_near(handle, params, &periods, &dir)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_periods_near failed.\n");
return err;
}
/* Write the parameters to the driver */
if ((err = snd_pcm_hw_params(handle, params)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params failed.\n");
return err;
}
return 0;
}
void get_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params)
{
int val;
int dir;
snd_pcm_uframes_t frames;
printf("\n*** Display information about the PCM interface ***\n");
printf(" ALSA library version: %s\n", SND_LIB_VERSION_STR);
printf(" PCM handle name = %s\n", snd_pcm_name(handle));
printf(" PCM state = %s\n", snd_pcm_state_name(snd_pcm_state(handle)));
snd_pcm_hw_params_get_access(params, (snd_pcm_access_t*)&val);
printf(" Access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)&val);
printf(" Fotmat = %s ", snd_pcm_format_name((snd_pcm_format_t)val));
printf("(%s)\n", snd_pcm_format_description((snd_pcm_format_t)val));
snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t*)&val);
printf(" Subformat = %s ", snd_pcm_subformat_name((snd_pcm_subformat_t)val));
printf("(%s)\n", snd_pcm_subformat_description((snd_pcm_subformat_t)val));
snd_pcm_hw_params_get_channels(params, &val);
printf(" Channels = %d\n", val);
snd_pcm_hw_params_get_rate(params, &val, &dir);
printf(" Sampling rate = %d\n", val);
snd_pcm_hw_params_get_period_time(params, &val, &dir);
printf(" Period time = %d us (= %d ms)\n", val, val/1000);
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
printf(" Period size = %d frames\n", (int)frames);
snd_pcm_hw_params_get_buffer_time(params, &val, &dir);
printf(" Buffer time = %d us (= %d ms)\n", val, val/1000);
snd_pcm_hw_params_get_buffer_size(params, &frames);
printf(" Buffer size = %d frames\n", (int)frames);
snd_pcm_hw_params_get_periods(params, &val, &dir);
printf(" Periods per buffer = %d periods\n", val);
printf("\n");
}
# build mode
release : make
debug : make debug
# clean
make clean
@Makefile
SRC=alsa_playback.c
TARGET=playback
LIB=asound
target:
gcc -o${TARGET} ${SRC} -l${LIB}
debug:
gcc -DDEBUG -o${TARGET} ${SRC} -l${LIB}
clean:
rm -rf ${TARGET}
@ source
/* Use the newer ALSA API */
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <stdio.h>
#include <stdint.h>
#define BUF_SIZE (30*16000)
#define WR_SIZE (2048) // Why 2048 ???
void SetParameters(snd_pcm_t* handle, snd_pcm_hw_params_t* params);
void Playback(snd_pcm_t* handle, const char* sndfile);
int set_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params);
void get_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params);
int LoadSoundfile(const char* filename, uint8_t* buffer);
int main(int argc, char* argv[])
{
int err;
snd_pcm_t* handle;
snd_pcm_hw_params_t* params;
if (argc != 2)
{
fprintf(stderr, "Usage: ./playback [input_snd_file]\n");
exit(EXIT_FAILURE);
}
/* Open PCM device for playback */
if ((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
fprintf(stderr, "snd_pcm_open failed.\n");
exit(EXIT_FAILURE);
}
/* Allocate a hardware parameters object */
snd_pcm_hw_params_alloca(¶ms);
/* Setting Parameters */
SetParameters(handle, params);
/* Simple sound playback */
Playback(handle, argv[1]);
/* Close PCM device */
snd_pcm_close(handle);
return 0;
}
void Playback(snd_pcm_t* handle, const char* sndfile)
{
int err;
int16_t readBuffer[BUF_SIZE] = {0,};
int16_t* offset = readBuffer;
int fileSize=0, readSize=0;
/* Load a SoundFile */
fileSize = LoadSoundfile(sndfile, (uint8_t*)readBuffer);
/* Playback Loop until EOF */
while (offset - readBuffer <= fileSize)
{
int nRead = snd_pcm_writei(handle, offset, WR_SIZE);
#ifdef DEBUG
fprintf(stderr, "nRead(%d) => offsetSize(%d) / totalSize(%d)\n"
, nRead, offset - readBuffer, fileSize);
#endif
if (nRead == 0)
{
fprintf(stderr, "End of file on input\n");
}
else if (nRead == -EPIPE)
{
fprintf(stderr, "Underrun occurred.\n");
snd_pcm_prepare(handle);
nRead = 0;
}
else if (nRead < 0)
{
fprintf(stderr, "Read error.\n");
exit(EXIT_FAILURE);
}
usleep(10000);
offset += nRead;
}
}
int LoadSoundfile(const char* filename, uint8_t* buffer)
{
int nFileSize;
FILE* fp = fopen(filename, "r");
memset(buffer, 0, BUF_SIZE);
nFileSize = fread((int8_t*)buffer, sizeof(int16_t), BUF_SIZE, fp);
printf(" -> FileSize = %d\n", nFileSize);
return nFileSize;
}
void SetParameters(snd_pcm_t* handle, snd_pcm_hw_params_t* params)
{
int err;
/* Configure HW parameters */
if ((err = set_hw_params(handle, params)) < 0)
{
fprintf(stderr, "set_hw_params failed: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
#ifdef DEBUG
/* Display information about the PCM interface */
get_hw_params(handle, params);
#endif
}
int set_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params)
{
int err;
int channels;
int rate, direction, target;
snd_pcm_uframes_t period_size;
int periods, dir;
printf("*** Set pcm hw parameters ***\n");
/* Fill it in with default values */
if ((err = snd_pcm_hw_params_any(handle, params)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_any failed.\n");
return err;
}
/* Read/Write Interleaved mode */
if ((err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_access failed.\n");
return err;
}
/* Signed 16-bit little-endian format */
if ((err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_format failed.\n");
return err;
}
/* Mono channel, 1: mono, 2: stereo */
channels = 1;
if ((err = snd_pcm_hw_params_set_channels(handle, params, channels)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_channels failed.\n");
exit(EXIT_FAILURE);
}
/* 16 kbps sampling rate */
target = rate = 16000;
if ((err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_rate_near failed.\n");
return err;
}
/* 128 frames per period */
period_size = 128;
if ((err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, &dir)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_period_size_near failed.\n");
return err;
}
/* 16 periods per buffer */
periods = 16;
if ((err = snd_pcm_hw_params_set_periods_near(handle, params, &periods, &dir)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params_set_periods_near failed.\n");
return err;
}
/* Write the parameters to the driver */
if ((err = snd_pcm_hw_params(handle, params)) < 0)
{
fprintf(stderr, "snd_pcm_hw_params failed.\n");
return err;
}
return 0;
}
void get_hw_params(snd_pcm_t* handle, snd_pcm_hw_params_t* params)
{
int val;
int dir;
snd_pcm_uframes_t frames;
printf("\n*** Display information about the PCM interface ***\n");
printf(" ALSA library version: %s\n", SND_LIB_VERSION_STR);
printf(" PCM handle name = %s\n", snd_pcm_name(handle));
printf(" PCM state = %s\n", snd_pcm_state_name(snd_pcm_state(handle)));
snd_pcm_hw_params_get_access(params, (snd_pcm_access_t*)&val);
printf(" Access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)&val);
printf(" Fotmat = %s ", snd_pcm_format_name((snd_pcm_format_t)val));
printf("(%s)\n", snd_pcm_format_description((snd_pcm_format_t)val));
snd_pcm_hw_params_get_subformat(params, (snd_pcm_subformat_t*)&val);
printf(" Subformat = %s ", snd_pcm_subformat_name((snd_pcm_subformat_t)val));
printf("(%s)\n", snd_pcm_subformat_description((snd_pcm_subformat_t)val));
snd_pcm_hw_params_get_channels(params, &val);
printf(" Channels = %d\n", val);
snd_pcm_hw_params_get_rate(params, &val, &dir);
printf(" Sampling rate = %d\n", val);
snd_pcm_hw_params_get_period_time(params, &val, &dir);
printf(" Period time = %d us (= %d ms)\n", val, val/1000);
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
printf(" Period size = %d frames\n", (int)frames);
snd_pcm_hw_params_get_buffer_time(params, &val, &dir);
printf(" Buffer time = %d us (= %d ms)\n", val, val/1000);
snd_pcm_hw_params_get_buffer_size(params, &frames);
printf(" Buffer size = %d frames\n", (int)frames);
snd_pcm_hw_params_get_periods(params, &val, &dir);
printf(" Periods per buffer = %d periods\n", val);
printf("\n");
}
No comments:
Post a Comment