mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-12-23 07:06:31 +01:00
Merged pcm-v2 branch into main CVS tree.
This commit is contained in:
parent
5a6a0836c9
commit
bf4f126205
1 changed files with 383 additions and 157 deletions
538
aplay/aplay.c
538
aplay/aplay.c
|
@ -52,20 +52,39 @@
|
||||||
|
|
||||||
char *command;
|
char *command;
|
||||||
snd_pcm_t *pcm_handle;
|
snd_pcm_t *pcm_handle;
|
||||||
struct snd_pcm_playback_info pinfo;
|
struct snd_pcm_channel_info cinfo;
|
||||||
struct snd_pcm_capture_info rinfo;
|
|
||||||
snd_pcm_format_t rformat, format;
|
snd_pcm_format_t rformat, format;
|
||||||
int timelimit = 0;
|
int timelimit = 0;
|
||||||
int quiet_mode = 0;
|
int quiet_mode = 0;
|
||||||
int verbose_mode = 0;
|
int verbose_mode = 0;
|
||||||
|
int format_change = 0;
|
||||||
int active_format = FORMAT_DEFAULT;
|
int active_format = FORMAT_DEFAULT;
|
||||||
|
int mode = SND_PCM_MODE_BLOCK;
|
||||||
int direction = SND_PCM_OPEN_PLAYBACK;
|
int direction = SND_PCM_OPEN_PLAYBACK;
|
||||||
|
int channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||||
|
int mmap_flag = 0;
|
||||||
|
int frag = 0;
|
||||||
|
int frags = 0;
|
||||||
char *audiobuf = NULL;
|
char *audiobuf = NULL;
|
||||||
|
snd_pcm_mmap_control_t *mmap_control = NULL;
|
||||||
|
char *mmap_data = NULL;
|
||||||
|
long mmap_size = 0;
|
||||||
int buffer_size = -1;
|
int buffer_size = -1;
|
||||||
|
char silence = 0;
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
int vocmajor, vocminor;
|
int vocmajor, vocminor;
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
|
||||||
|
int (*fcn_info)(snd_pcm_t *handle, snd_pcm_channel_info_t *info);
|
||||||
|
int (*fcn_params)(snd_pcm_t *handle, snd_pcm_channel_params_t *params);
|
||||||
|
int (*fcn_setup)(snd_pcm_t *handle, snd_pcm_channel_setup_t *setup);
|
||||||
|
int (*fcn_status)(snd_pcm_t *handle, snd_pcm_channel_status_t *status);
|
||||||
|
int (*fcn_flush)(snd_pcm_t *handle, int channel);
|
||||||
|
ssize_t (*fcn_write)(snd_pcm_t *handle, const void *buffer, size_t size);
|
||||||
|
ssize_t (*fcn_read)(snd_pcm_t *handle, void *buffer, size_t size);
|
||||||
|
|
||||||
/* needed prototypes */
|
/* needed prototypes */
|
||||||
|
|
||||||
static void playback(char *filename);
|
static void playback(char *filename);
|
||||||
|
@ -92,15 +111,27 @@ static char *get_format(int format)
|
||||||
{
|
{
|
||||||
static char *formats[] =
|
static char *formats[] =
|
||||||
{
|
{
|
||||||
"Mu-Law",
|
"Signed 8-bit",
|
||||||
"A-Law",
|
|
||||||
"Ima-ADPCM",
|
|
||||||
"Unsigned 8-bit",
|
"Unsigned 8-bit",
|
||||||
"Signed 16-bit Little Endian",
|
"Signed 16-bit Little Endian",
|
||||||
"Signed 16-bit Big Endian",
|
"Signed 16-bit Big Endian",
|
||||||
"Signed 8-bit",
|
|
||||||
"Unsigned 16-bit Little Endian",
|
"Unsigned 16-bit Little Endian",
|
||||||
"Unsigned 16-bit Big Endian",
|
"Unsigned 16-bit Big Endian",
|
||||||
|
"Signed 24-bit Little Endian",
|
||||||
|
"Signed 24-bit Big Endian",
|
||||||
|
"Unsigned 24-bit Little Endian",
|
||||||
|
"Unsigned 24-bit Big Endian",
|
||||||
|
"Signed 32-bit Little Endian",
|
||||||
|
"Signed 32-bit Big Endian",
|
||||||
|
"Unsigned 32-bit Little Endian",
|
||||||
|
"Unsigned 32-bit Big Endian",
|
||||||
|
"Float",
|
||||||
|
"Float64",
|
||||||
|
"IEC-958 Little Endian",
|
||||||
|
"IEC-958 Big Endian",
|
||||||
|
"Mu-Law",
|
||||||
|
"A-Law",
|
||||||
|
"Ima-ADPCM",
|
||||||
"MPEG",
|
"MPEG",
|
||||||
"GSM"
|
"GSM"
|
||||||
};
|
};
|
||||||
|
@ -111,24 +142,13 @@ static char *get_format(int format)
|
||||||
|
|
||||||
static void check_new_format(snd_pcm_format_t * format)
|
static void check_new_format(snd_pcm_format_t * format)
|
||||||
{
|
{
|
||||||
if (direction == SND_PCM_OPEN_PLAYBACK) {
|
if (cinfo.min_rate > format->rate || cinfo.max_rate < format->rate) {
|
||||||
if (pinfo.min_rate > format->rate || pinfo.max_rate < format->rate) {
|
fprintf(stderr, "%s: unsupported rate %iHz (valid range is %iHz-%iHz)\n", command, format->rate, cinfo.min_rate, cinfo.max_rate);
|
||||||
fprintf(stderr, "%s: unsupported rate %iHz for playback (valid range is %iHz-%iHz)\n", command, format->rate, pinfo.min_rate, pinfo.max_rate);
|
exit(1);
|
||||||
exit(1);
|
}
|
||||||
}
|
if (!(cinfo.formats & (1 << format->format))) {
|
||||||
if (!(pinfo.formats & (1 << format->format))) {
|
fprintf(stderr, "%s: requested format %s isn't supported with hardware\n", command, get_format(format->format));
|
||||||
fprintf(stderr, "%s: requested format %s isn't supported with hardware\n", command, get_format(format->format));
|
exit(1);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (rinfo.min_rate > format->rate || rinfo.max_rate < format->rate) {
|
|
||||||
fprintf(stderr, "%s: unsupported rate %iHz for capture (valid range is %iHz-%iHz)\n", command, format->rate, rinfo.min_rate, rinfo.max_rate);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (!(rinfo.formats & (1 << format->format))) {
|
|
||||||
fprintf(stderr, "%s: requested format %s isn't supported with hardware\n", command, get_format(rformat.format));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +175,8 @@ static void usage(char *command)
|
||||||
" -m set CD-ROM quality (44100Hz,stereo,16-bit linear)\n"
|
" -m set CD-ROM quality (44100Hz,stereo,16-bit linear)\n"
|
||||||
" -M set DAT quality (48000Hz,stereo,16-bit linear)\n"
|
" -M set DAT quality (48000Hz,stereo,16-bit linear)\n"
|
||||||
" -p <type> compression type (alaw, ulaw, adpcm)\n"
|
" -p <type> compression type (alaw, ulaw, adpcm)\n"
|
||||||
|
" -e stream mode\n"
|
||||||
|
" -E mmap mode\n"
|
||||||
,command, snd_cards()-1);
|
,command, snd_cards()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +187,7 @@ static void device_list(void)
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
struct snd_ctl_hw_info info;
|
struct snd_ctl_hw_info info;
|
||||||
snd_pcm_info_t pcminfo;
|
snd_pcm_info_t pcminfo;
|
||||||
snd_pcm_playback_info_t playinfo;
|
snd_pcm_channel_info_t chninfo;
|
||||||
snd_pcm_capture_info_t recinfo;
|
|
||||||
|
|
||||||
mask = snd_cards_mask();
|
mask = snd_cards_mask();
|
||||||
if (!mask) {
|
if (!mask) {
|
||||||
|
@ -203,32 +224,24 @@ static void device_list(void)
|
||||||
printf(" Playback subdevices: %i\n", pcminfo.playback + 1);
|
printf(" Playback subdevices: %i\n", pcminfo.playback + 1);
|
||||||
printf(" Capture subdevices: %i\n", pcminfo.capture + 1);
|
printf(" Capture subdevices: %i\n", pcminfo.capture + 1);
|
||||||
if (pcminfo.flags & SND_PCM_INFO_PLAYBACK) {
|
if (pcminfo.flags & SND_PCM_INFO_PLAYBACK) {
|
||||||
if ((err = snd_ctl_pcm_playback_info(handle, dev, 0, &playinfo)) < 0) {
|
for (idx = 0; idx <= pcminfo.playback; idx++) {
|
||||||
printf("Error: control digital audio playback info (%i): %s\n", card, snd_strerror(err));
|
memset(&chninfo, 0, sizeof(chninfo));
|
||||||
} else {
|
chninfo.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||||
printf(" Playback:\n");
|
if ((err = snd_ctl_pcm_channel_info(handle, dev, idx, &chninfo)) < 0) {
|
||||||
printf(" Rate range: %iHz-%iHz\n", playinfo.min_rate, playinfo.max_rate);
|
printf("Error: control digital audio playback info (%i): %s\n", card, snd_strerror(err));
|
||||||
printf(" Voices range: %i-%i\n", playinfo.min_channels, playinfo.max_channels);
|
} else {
|
||||||
printf(" Formats:\n");
|
printf(" Playback subdevice #%i: %s\n", idx, chninfo.subname);
|
||||||
for (idx = 0; idx < SND_PCM_SFMT_GSM; idx++) {
|
|
||||||
if (playinfo.formats & (1 << idx))
|
|
||||||
printf(" %s%s\n", get_format(idx),
|
|
||||||
playinfo.hw_formats & (1 << idx) ? " [hardware]" : "");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pcminfo.flags & SND_PCM_INFO_CAPTURE) {
|
if (pcminfo.flags & SND_PCM_INFO_CAPTURE) {
|
||||||
if ((err = snd_ctl_pcm_capture_info(handle, dev, 0, &recinfo)) < 0) {
|
for (idx = 0; idx <= pcminfo.capture; idx++) {
|
||||||
printf("Error: control digital audio capture info (%i): %s\n", card, snd_strerror(err));
|
memset(&chninfo, 0, sizeof(chninfo));
|
||||||
} else {
|
chninfo.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||||
printf(" Record:\n");
|
if ((err = snd_ctl_pcm_channel_info(handle, dev, 0, &chninfo)) < 0) {
|
||||||
printf(" Rate range: %iHz-%iHz\n", recinfo.min_rate, recinfo.max_rate);
|
printf("Error: control digital audio capture info (%i): %s\n", card, snd_strerror(err));
|
||||||
printf(" Voices range: %i-%i\n", recinfo.min_channels, recinfo.max_channels);
|
} else {
|
||||||
printf(" Formats:\n");
|
printf(" Capture subdevice #%i: %s\n", idx, chninfo.subname);
|
||||||
for (idx = 0; idx < SND_PCM_SFMT_GSM; idx++) {
|
|
||||||
if (recinfo.formats & (1 << idx))
|
|
||||||
printf(" %s%s\n", get_format(idx),
|
|
||||||
recinfo.hw_formats & (1 << idx) ? " [hardware]" : "");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +252,7 @@ static void device_list(void)
|
||||||
|
|
||||||
static void version(void)
|
static void version(void)
|
||||||
{
|
{
|
||||||
printf("%s: version " SND_UTIL_VERSION_STR " by Jaroslav Kysela <perex@suse.cz>\n", command);
|
fprintf(stderr, "%s: version " SND_UTIL_VERSION_STR " by Jaroslav Kysela <perex@suse.cz>\n", command);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -252,10 +265,12 @@ int main(int argc, char *argv[])
|
||||||
active_format = FORMAT_DEFAULT;
|
active_format = FORMAT_DEFAULT;
|
||||||
if (strstr(argv[0], "arecord")) {
|
if (strstr(argv[0], "arecord")) {
|
||||||
direction = SND_PCM_OPEN_CAPTURE;
|
direction = SND_PCM_OPEN_CAPTURE;
|
||||||
|
channel = SND_PCM_CHANNEL_CAPTURE;
|
||||||
active_format = FORMAT_WAVE;
|
active_format = FORMAT_WAVE;
|
||||||
command = "Arecord";
|
command = "Arecord";
|
||||||
} else if (strstr(argv[0], "aplay")) {
|
} else if (strstr(argv[0], "aplay")) {
|
||||||
direction = SND_PCM_OPEN_PLAYBACK;
|
direction = SND_PCM_OPEN_PLAYBACK;
|
||||||
|
channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||||
command = "Aplay";
|
command = "Aplay";
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Error: command should be named either arecord or aplay\n");
|
fprintf(stderr, "Error: command should be named either arecord or aplay\n");
|
||||||
|
@ -264,9 +279,10 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
buffer_size = -1;
|
buffer_size = -1;
|
||||||
memset(&rformat, 0, sizeof(rformat));
|
memset(&rformat, 0, sizeof(rformat));
|
||||||
|
rformat.interleave = 1;
|
||||||
rformat.format = SND_PCM_SFMT_U8;
|
rformat.format = SND_PCM_SFMT_U8;
|
||||||
rformat.rate = DEFAULT_SPEED;
|
rformat.rate = DEFAULT_SPEED;
|
||||||
rformat.channels = 1;
|
rformat.voices = 1;
|
||||||
|
|
||||||
if (argc > 1 && !strcmp(argv[1], "--help")) {
|
if (argc > 1 && !strcmp(argv[1], "--help")) {
|
||||||
usage(command);
|
usage(command);
|
||||||
|
@ -276,7 +292,7 @@ int main(int argc, char *argv[])
|
||||||
version();
|
version();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while ((c = getopt(argc, argv, "hlc:d:qs:So:t:b:vrwuxB:c:p:mMV")) != EOF)
|
while ((c = getopt(argc, argv, "hlc:d:qs:So:t:b:vrwuxB:c:p:mMVeE")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(command);
|
usage(command);
|
||||||
|
@ -299,12 +315,12 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
rformat.channels = 2;
|
rformat.voices = 2;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
tmp = atoi(optarg);
|
tmp = atoi(optarg);
|
||||||
if (tmp < 1 || tmp > 32) {
|
if (tmp < 1 || tmp > 32) {
|
||||||
fprintf(stderr, "Error: value %i for channels is invalid\n", tmp);
|
fprintf(stderr, "Error: value %i for voices is invalid\n", tmp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -373,11 +389,24 @@ int main(int argc, char *argv[])
|
||||||
case 'M':
|
case 'M':
|
||||||
rformat.format = SND_PCM_SFMT_S16_LE;
|
rformat.format = SND_PCM_SFMT_S16_LE;
|
||||||
rformat.rate = c == 'M' ? 48000 : 44100;
|
rformat.rate = c == 'M' ? 48000 : 44100;
|
||||||
rformat.channels = 2;
|
rformat.voices = 2;
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
version();
|
version();
|
||||||
return 0;
|
return 0;
|
||||||
|
case 'e':
|
||||||
|
if (!mmap_flag) {
|
||||||
|
mode = SND_PCM_MODE_STREAM;
|
||||||
|
if (direction == SND_PCM_OPEN_CAPTURE)
|
||||||
|
direction = SND_PCM_OPEN_STREAM_CAPTURE;
|
||||||
|
if (direction == SND_PCM_OPEN_PLAYBACK)
|
||||||
|
direction = SND_PCM_OPEN_STREAM_PLAYBACK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
if (mode == SND_PCM_MODE_BLOCK)
|
||||||
|
mmap_flag = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(command);
|
usage(command);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -386,46 +415,51 @@ int main(int argc, char *argv[])
|
||||||
if (!quiet_mode)
|
if (!quiet_mode)
|
||||||
version();
|
version();
|
||||||
|
|
||||||
|
fcn_info = snd_pcm_plugin_info;
|
||||||
|
fcn_params = snd_pcm_plugin_params;
|
||||||
|
fcn_setup = snd_pcm_plugin_setup;
|
||||||
|
fcn_status = snd_pcm_plugin_status;
|
||||||
|
fcn_flush = snd_pcm_plugin_flush;
|
||||||
|
fcn_write = snd_pcm_plugin_write;
|
||||||
|
fcn_read = snd_pcm_plugin_read;
|
||||||
|
if (mmap_flag) {
|
||||||
|
fcn_info = snd_pcm_channel_info;
|
||||||
|
fcn_params = snd_pcm_channel_params;
|
||||||
|
fcn_setup = snd_pcm_channel_setup;
|
||||||
|
fcn_status = snd_pcm_channel_status;
|
||||||
|
fcn_flush = snd_pcm_flush_channel;
|
||||||
|
fcn_write = snd_pcm_write;
|
||||||
|
fcn_read = snd_pcm_read;
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = snd_pcm_open(&pcm_handle, card, dev, direction)) < 0) {
|
if ((err = snd_pcm_open(&pcm_handle, card, dev, direction)) < 0) {
|
||||||
fprintf(stderr, "Error: audio open error: %s\n", snd_strerror(err));
|
fprintf(stderr, "Error: audio open error: %s\n", snd_strerror(err));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (direction == SND_PCM_OPEN_PLAYBACK) {
|
memset(&cinfo, 0, sizeof(cinfo));
|
||||||
if ((err = snd_pcm_playback_info(pcm_handle, &pinfo)) < 0) {
|
cinfo.channel = channel;
|
||||||
fprintf(stderr, "Error: playback info error: %s\n", snd_strerror(err));
|
if ((err = fcn_info(pcm_handle, &cinfo)) < 0) {
|
||||||
return 1;
|
fprintf(stderr, "Error: channel info error: %s\n", snd_strerror(err));
|
||||||
}
|
|
||||||
tmp = pinfo.buffer_size;
|
|
||||||
tmp /= 4; /* 4 fragments are best */
|
|
||||||
} else {
|
|
||||||
if ((err = snd_pcm_capture_info(pcm_handle, &rinfo)) < 0) {
|
|
||||||
fprintf(stderr, "Error: capture info error: %s\n", snd_strerror(err));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
tmp = rinfo.buffer_size;
|
|
||||||
tmp /= 8; /* 8 fragments are best */
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_size = tmp;
|
|
||||||
if (buffer_size < 512 || buffer_size > 16L * 1024L * 1024L) {
|
|
||||||
fprintf(stderr, "Error: Invalid audio buffer size %d\n", buffer_size);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
check_new_format(&rformat);
|
|
||||||
|
buffer_size = 1024;
|
||||||
format = rformat;
|
format = rformat;
|
||||||
|
|
||||||
if ((audiobuf = malloc(buffer_size)) == NULL) {
|
audiobuf = (char *)malloc(1024);
|
||||||
fprintf(stderr, "%s: unable to allocate input/output buffer\n", command);
|
if (audiobuf == NULL) {
|
||||||
|
fprintf(stderr, "Error: not enough memory\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind > argc - 1) {
|
if (optind > argc - 1) {
|
||||||
if (direction == SND_PCM_OPEN_PLAYBACK)
|
if (channel == SND_PCM_CHANNEL_PLAYBACK)
|
||||||
playback(NULL);
|
playback(NULL);
|
||||||
else
|
else
|
||||||
capture(NULL);
|
capture(NULL);
|
||||||
} else {
|
} else {
|
||||||
while (optind <= argc - 1) {
|
while (optind <= argc - 1) {
|
||||||
if (direction == SND_PCM_OPEN_PLAYBACK)
|
if (channel == SND_PCM_CHANNEL_PLAYBACK)
|
||||||
playback(argv[optind++]);
|
playback(argv[optind++]);
|
||||||
else
|
else
|
||||||
capture(argv[optind++]);
|
capture(argv[optind++]);
|
||||||
|
@ -472,7 +506,7 @@ static int test_wavefile(void *buffer)
|
||||||
command, wp->modus);
|
command, wp->modus);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
format.channels = wp->modus;
|
format.voices = wp->modus;
|
||||||
switch (wp->bit_p_spl) {
|
switch (wp->bit_p_spl) {
|
||||||
case 8:
|
case 8:
|
||||||
format.format = SND_PCM_SFMT_U8;
|
format.format = SND_PCM_SFMT_U8;
|
||||||
|
@ -521,8 +555,8 @@ static int test_au(int fd, void *buffer)
|
||||||
format.rate = ntohl(ap->sample_rate);
|
format.rate = ntohl(ap->sample_rate);
|
||||||
if (format.rate < 2000 || format.rate > 256000)
|
if (format.rate < 2000 || format.rate > 256000)
|
||||||
return -1;
|
return -1;
|
||||||
format.channels = ntohl(ap->channels);
|
format.voices = ntohl(ap->channels);
|
||||||
if (format.channels < 1 || format.channels > 128)
|
if (format.voices < 1 || format.voices > 128)
|
||||||
return -1;
|
return -1;
|
||||||
if (read(fd, buffer + sizeof(AuHeader), ntohl(ap->hdr_size) - sizeof(AuHeader)) < 0) {
|
if (read(fd, buffer + sizeof(AuHeader), ntohl(ap->hdr_size) - sizeof(AuHeader)) < 0) {
|
||||||
fprintf(stderr, "%s: read error\n", command);
|
fprintf(stderr, "%s: read error\n", command);
|
||||||
|
@ -551,7 +585,7 @@ static void write_zeros(unsigned x)
|
||||||
l = x;
|
l = x;
|
||||||
if (l > buffer_size)
|
if (l > buffer_size)
|
||||||
l = buffer_size;
|
l = buffer_size;
|
||||||
if (snd_pcm_write(pcm_handle, buf, l) != l) {
|
if (fcn_write(pcm_handle, buf, l) != l) {
|
||||||
fprintf(stderr, "%s: write error\n", command);
|
fprintf(stderr, "%s: write error\n", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -563,54 +597,99 @@ static void set_format(void)
|
||||||
{
|
{
|
||||||
unsigned int bps; /* bytes per second */
|
unsigned int bps; /* bytes per second */
|
||||||
unsigned int size; /* fragment size */
|
unsigned int size; /* fragment size */
|
||||||
struct snd_pcm_playback_params pparams;
|
struct snd_pcm_channel_params params;
|
||||||
struct snd_pcm_capture_params rparams;
|
struct snd_pcm_channel_setup setup;
|
||||||
|
|
||||||
bps = format.rate * format.channels;
|
if (!format_change)
|
||||||
|
return;
|
||||||
|
bps = format.rate * format.voices;
|
||||||
|
silence = 0x00;
|
||||||
switch (format.format) {
|
switch (format.format) {
|
||||||
|
case SND_PCM_SFMT_U8:
|
||||||
|
silence = 0x80;
|
||||||
|
break;
|
||||||
case SND_PCM_SFMT_U16_LE:
|
case SND_PCM_SFMT_U16_LE:
|
||||||
case SND_PCM_SFMT_U16_BE:
|
case SND_PCM_SFMT_U16_BE:
|
||||||
bps <<= 1;
|
bps <<= 1;
|
||||||
|
silence = 0x80;
|
||||||
|
break;
|
||||||
|
case SND_PCM_SFMT_S8:
|
||||||
|
silence = 0x00;
|
||||||
|
break;
|
||||||
|
case SND_PCM_SFMT_S16_LE:
|
||||||
|
case SND_PCM_SFMT_S16_BE:
|
||||||
|
bps <<= 1;
|
||||||
|
silence = 0x00;
|
||||||
break;
|
break;
|
||||||
case SND_PCM_SFMT_IMA_ADPCM:
|
case SND_PCM_SFMT_IMA_ADPCM:
|
||||||
bps >>= 2;
|
bps >>= 2;
|
||||||
|
silence = 0x00;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bps >>= 2; /* ok.. this buffer should be 0.25 sec */
|
bps >>= 2; /* ok.. this buffer should be 0.25 sec */
|
||||||
if (bps < 16)
|
if (bps < 16)
|
||||||
bps = 16;
|
bps = 16;
|
||||||
size = buffer_size;
|
size = 1;
|
||||||
while (size > bps)
|
while ((size << 1) < bps)
|
||||||
size >>= 1;
|
size <<= 1;
|
||||||
if (size < 16)
|
|
||||||
size = 16;
|
|
||||||
|
|
||||||
if (direction == SND_PCM_OPEN_PLAYBACK) {
|
if (mmap_flag)
|
||||||
if (snd_pcm_playback_format(pcm_handle, &format) < 0) {
|
snd_pcm_munmap(pcm_handle, channel);
|
||||||
fprintf(stderr, "%s: unable to set playback format %s, %iHz, %i voices\n", command, get_format(format.format), format.rate, format.channels);
|
fcn_flush(pcm_handle, channel); /* to be in right state */
|
||||||
exit(1);
|
memset(¶ms, 0, sizeof(params));
|
||||||
}
|
params.mode = mode;
|
||||||
memset(&pparams, 0, sizeof(pparams));
|
params.channel = channel;
|
||||||
pparams.fragment_size = size;
|
memcpy(¶ms.format, &format, sizeof(format));
|
||||||
pparams.fragments_max = -1; /* little trick */
|
if (channel == SND_PCM_CHANNEL_PLAYBACK) {
|
||||||
pparams.fragments_room = 1;
|
params.start_mode = SND_PCM_START_FULL;
|
||||||
if (snd_pcm_playback_params(pcm_handle, &pparams) < 0) {
|
|
||||||
fprintf(stderr, "%s: unable to set playback params\n", command);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (snd_pcm_capture_format(pcm_handle, &format) < 0) {
|
params.start_mode = SND_PCM_START_DATA;
|
||||||
fprintf(stderr, "%s: unable to set capture format %s, %iHz, %i voices\n", command, get_format(format.format), format.rate, format.channels);
|
}
|
||||||
exit(1);
|
params.stop_mode = SND_PCM_STOP_STOP;
|
||||||
}
|
if (mode == SND_PCM_MODE_BLOCK) {
|
||||||
memset(&rparams, 0, sizeof(rparams));
|
params.buf.block.frag_size = size;
|
||||||
rparams.fragment_size = size;
|
// params.buf.block.frag_size = 128;
|
||||||
rparams.fragments_min = 1;
|
params.buf.block.frags_max = -1; /* little trick (playback only) */
|
||||||
if (snd_pcm_capture_params(pcm_handle, &rparams) < 0) {
|
// params.buf.block.frags_max = 1;
|
||||||
fprintf(stderr, "%s: unable to set capture params\n", command);
|
params.buf.block.frags_min = 1;
|
||||||
|
} else {
|
||||||
|
params.buf.stream.queue_size = 1024 * 1024; /* maximum */
|
||||||
|
// params.buf.stream.queue_size = 8192;
|
||||||
|
params.buf.stream.fill = SND_PCM_FILL_SILENCE;
|
||||||
|
params.buf.stream.max_fill = 1024;
|
||||||
|
}
|
||||||
|
if (fcn_params(pcm_handle, ¶ms) < 0) {
|
||||||
|
fprintf(stderr, "%s: unable to set channel params\n", command);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (mmap_flag) {
|
||||||
|
if (snd_pcm_mmap(pcm_handle, channel, &mmap_control, (void **)&mmap_data)<0) {
|
||||||
|
fprintf(stderr, "%s: unable to mmap memory\n", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (snd_pcm_channel_prepare(pcm_handle, channel) < 0) {
|
||||||
|
fprintf(stderr, "%s: unable to prepare channel\n", command);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(&setup, 0, sizeof(setup));
|
||||||
|
setup.mode = mode;
|
||||||
|
setup.channel = channel;
|
||||||
|
if (fcn_setup(pcm_handle, &setup) < 0) {
|
||||||
|
fprintf(stderr, "%s: unable to obtain setup\n", command);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
frags = setup.buf.block.frags;
|
||||||
|
buffer_size = mode == SND_PCM_MODE_BLOCK ?
|
||||||
|
setup.buf.block.frag_size :
|
||||||
|
setup.buf.stream.queue_size;
|
||||||
|
audiobuf = (char *)realloc(audiobuf, buffer_size);
|
||||||
|
if (audiobuf == NULL) {
|
||||||
|
fprintf(stderr, "%s: not enough memory\n", command);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// printf("real buffer_size = %i, frags = %i, total = %i\n", buffer_size, setup.buf.block.frags, setup.buf.block.frags * buffer_size);
|
||||||
|
format_change = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -650,8 +729,9 @@ static void voc_play(int fd, int ofs, char *name)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
format.format = SND_PCM_SFMT_U8;
|
format.format = SND_PCM_SFMT_U8;
|
||||||
format.channels = 1;
|
format.voices = 1;
|
||||||
format.rate = DEFAULT_SPEED;
|
format.rate = DEFAULT_SPEED;
|
||||||
|
format_change = 1;
|
||||||
set_format();
|
set_format();
|
||||||
|
|
||||||
in_buffer = nextblock = 0;
|
in_buffer = nextblock = 0;
|
||||||
|
@ -704,14 +784,13 @@ static void voc_play(int fd, int ofs, char *name)
|
||||||
fprintf(stderr, "%s: can't play packed .voc files\n", command);
|
fprintf(stderr, "%s: can't play packed .voc files\n", command);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (format.channels == 2) { /* if we are in Stereo-Mode, switch back */
|
if (format.voices == 2) /* if we are in Stereo-Mode, switch back */
|
||||||
format.channels = 1;
|
format.voices = 1;
|
||||||
set_format();
|
|
||||||
}
|
|
||||||
} else { /* there was extended block */
|
} else { /* there was extended block */
|
||||||
format.channels = 2;
|
format.voices = 2;
|
||||||
was_extended = 0;
|
was_extended = 0;
|
||||||
}
|
}
|
||||||
|
format_change = 1;
|
||||||
set_format();
|
set_format();
|
||||||
break;
|
break;
|
||||||
case 2: /* nothing to do, pure data */
|
case 2: /* nothing to do, pure data */
|
||||||
|
@ -725,6 +804,7 @@ static void voc_play(int fd, int ofs, char *name)
|
||||||
format.rate = (int) (*data);
|
format.rate = (int) (*data);
|
||||||
COUNT1(1);
|
COUNT1(1);
|
||||||
format.rate = 1000000 / (256 - format.rate);
|
format.rate = 1000000 / (256 - format.rate);
|
||||||
|
format_change = 1;
|
||||||
set_format();
|
set_format();
|
||||||
silence = (((u_long) * sp) * 1000) / format.rate;
|
silence = (((u_long) * sp) * 1000) / format.rate;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -793,8 +873,8 @@ static void voc_play(int fd, int ofs, char *name)
|
||||||
COUNT1(sizeof(VocExtBlock));
|
COUNT1(sizeof(VocExtBlock));
|
||||||
format.rate = (int) (eb->tc);
|
format.rate = (int) (eb->tc);
|
||||||
format.rate = 256000000L / (65536 - format.rate);
|
format.rate = 256000000L / (65536 - format.rate);
|
||||||
format.channels = eb->mode == VOC_MODE_STEREO ? 2 : 1;
|
format.voices = eb->mode == VOC_MODE_STEREO ? 2 : 1;
|
||||||
if (format.channels == 2)
|
if (format.voices == 2)
|
||||||
format.rate = format.rate >> 1;
|
format.rate = format.rate >> 1;
|
||||||
if (eb->pack) { /* /dev/dsp can't it */
|
if (eb->pack) { /* /dev/dsp can't it */
|
||||||
fprintf(stderr, "%s: can't play packed .voc files\n", command);
|
fprintf(stderr, "%s: can't play packed .voc files\n", command);
|
||||||
|
@ -822,7 +902,7 @@ static void voc_play(int fd, int ofs, char *name)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (snd_pcm_write(pcm_handle, data, l) != l) {
|
if (fcn_write(pcm_handle, data, l) != l) {
|
||||||
fprintf(stderr, "%s: write error\n", command);
|
fprintf(stderr, "%s: write error\n", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -847,7 +927,7 @@ static u_long calc_count(void)
|
||||||
if (!timelimit)
|
if (!timelimit)
|
||||||
count = 0x7fffffff;
|
count = 0x7fffffff;
|
||||||
else {
|
else {
|
||||||
count = timelimit * format.rate * format.channels;
|
count = timelimit * format.rate * format.voices;
|
||||||
switch (format.format) {
|
switch (format.format) {
|
||||||
case SND_PCM_SFMT_S16_LE:
|
case SND_PCM_SFMT_S16_LE:
|
||||||
case SND_PCM_SFMT_S16_BE:
|
case SND_PCM_SFMT_S16_BE:
|
||||||
|
@ -881,7 +961,7 @@ static void begin_voc(int fd, u_long cnt)
|
||||||
fprintf(stderr, "%s: write error\n", command);
|
fprintf(stderr, "%s: write error\n", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (format.channels > 1) {
|
if (format.voices > 1) {
|
||||||
/* write a extended block */
|
/* write a extended block */
|
||||||
bt.type = 8;
|
bt.type = 8;
|
||||||
bt.datalen = 4;
|
bt.datalen = 4;
|
||||||
|
@ -939,7 +1019,7 @@ static void begin_wave(int fd, u_long cnt)
|
||||||
wh.sub_chunk = WAV_FMT;
|
wh.sub_chunk = WAV_FMT;
|
||||||
wh.sc_len = 16;
|
wh.sc_len = 16;
|
||||||
wh.format = WAV_PCM_CODE;
|
wh.format = WAV_PCM_CODE;
|
||||||
wh.modus = format.channels;
|
wh.modus = format.voices;
|
||||||
wh.sample_fq = format.rate;
|
wh.sample_fq = format.rate;
|
||||||
#if 0
|
#if 0
|
||||||
wh.byte_p_spl = (samplesize == 8) ? 1 : 2;
|
wh.byte_p_spl = (samplesize == 8) ? 1 : 2;
|
||||||
|
@ -972,7 +1052,7 @@ static void begin_au(int fd, u_long cnt)
|
||||||
case SND_PCM_SFMT_U8:
|
case SND_PCM_SFMT_U8:
|
||||||
ah.encoding = htonl(AU_FMT_LIN8);
|
ah.encoding = htonl(AU_FMT_LIN8);
|
||||||
break;
|
break;
|
||||||
case SND_PCM_SFMT_U16_LE:
|
case SND_PCM_SFMT_S16_LE:
|
||||||
ah.encoding = htonl(AU_FMT_LIN16);
|
ah.encoding = htonl(AU_FMT_LIN16);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -980,7 +1060,7 @@ static void begin_au(int fd, u_long cnt)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
ah.sample_rate = htonl(format.rate);
|
ah.sample_rate = htonl(format.rate);
|
||||||
ah.channels = htonl(format.channels);
|
ah.channels = htonl(format.voices);
|
||||||
if (write(fd, &ah, sizeof(AuHeader)) != sizeof(AuHeader)) {
|
if (write(fd, &ah, sizeof(AuHeader)) != sizeof(AuHeader)) {
|
||||||
fprintf(stderr, "%s: write error\n", command);
|
fprintf(stderr, "%s: write error\n", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -1009,56 +1089,158 @@ static void header(int rtype, char *name)
|
||||||
{
|
{
|
||||||
if (!quiet_mode) {
|
if (!quiet_mode) {
|
||||||
fprintf(stderr, "%s %s '%s' : ",
|
fprintf(stderr, "%s %s '%s' : ",
|
||||||
(direction == SND_PCM_OPEN_PLAYBACK) ? "Playing" : "Recording",
|
(channel == SND_PCM_CHANNEL_PLAYBACK) ? "Playing" : "Recording",
|
||||||
fmt_rec_table[rtype].what,
|
fmt_rec_table[rtype].what,
|
||||||
name);
|
name);
|
||||||
fprintf(stderr, "%s, ", get_format(format.format));
|
fprintf(stderr, "%s, ", get_format(format.format));
|
||||||
fprintf(stderr, "Rate %d Hz, ", format.rate);
|
fprintf(stderr, "Rate %d Hz, ", format.rate);
|
||||||
if (format.channels == 1)
|
if (format.voices == 1)
|
||||||
fprintf(stderr, "Mono");
|
fprintf(stderr, "Mono");
|
||||||
else if (format.channels == 2)
|
else if (format.voices == 2)
|
||||||
fprintf(stderr, "Stereo");
|
fprintf(stderr, "Stereo");
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Voices %i", format.channels);
|
fprintf(stderr, "Voices %i", format.voices);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* playback write error hander */
|
||||||
|
|
||||||
|
void playback_write_error(void)
|
||||||
|
{
|
||||||
|
snd_pcm_channel_status_t status;
|
||||||
|
|
||||||
|
memset(&status, 0, sizeof(status));
|
||||||
|
status.channel = channel;
|
||||||
|
if (fcn_status(pcm_handle, &status)<0) {
|
||||||
|
fprintf(stderr, "playback channel status error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (status.status == SND_PCM_STATUS_UNDERRUN) {
|
||||||
|
printf("underrun at position %u!!!\n", status.scount);
|
||||||
|
if (snd_pcm_channel_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)<0) {
|
||||||
|
fprintf(stderr, "underrun: playback channel prepare error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
frag = 0;
|
||||||
|
return; /* ok, data should be accepted again */
|
||||||
|
}
|
||||||
|
fprintf(stderr, "write error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* capture read error hander */
|
||||||
|
|
||||||
|
void capture_read_error(void)
|
||||||
|
{
|
||||||
|
snd_pcm_channel_status_t status;
|
||||||
|
|
||||||
|
memset(&status, 0, sizeof(status));
|
||||||
|
status.channel = channel;
|
||||||
|
if (fcn_status(pcm_handle, &status)<0) {
|
||||||
|
fprintf(stderr, "capture channel status error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (status.status == SND_PCM_STATUS_OVERRUN) {
|
||||||
|
printf("overrun at position %u!!!\n", status.scount);
|
||||||
|
if (snd_pcm_channel_prepare(pcm_handle, SND_PCM_CHANNEL_CAPTURE)<0) {
|
||||||
|
fprintf(stderr, "overrun: capture channel prepare error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
frag = 0;
|
||||||
|
return; /* ok, data should be accepted again */
|
||||||
|
}
|
||||||
|
fprintf(stderr, "read error\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* playing raw data */
|
/* playing raw data */
|
||||||
|
|
||||||
void playback_go(int fd, int loaded, u_long count, int rtype, char *name)
|
void playback_go(int fd, int loaded, u_long count, int rtype, char *name)
|
||||||
{
|
{
|
||||||
int l;
|
int l, r;
|
||||||
u_long c;
|
u_long c;
|
||||||
|
|
||||||
header(rtype, name);
|
header(rtype, name);
|
||||||
|
format_change = 1;
|
||||||
set_format();
|
set_format();
|
||||||
|
|
||||||
while (count) {
|
while (count) {
|
||||||
c = count;
|
l = loaded;
|
||||||
|
loaded = 0;
|
||||||
|
do {
|
||||||
|
c = count;
|
||||||
|
|
||||||
if (c > buffer_size)
|
if (c + l > buffer_size)
|
||||||
c = buffer_size;
|
c = buffer_size - l;
|
||||||
|
|
||||||
if ((l = read(fd, audiobuf + loaded, c - loaded)) > 0) {
|
if ((r = read(fd, audiobuf + l, c)) <= 0)
|
||||||
l += loaded;
|
break;
|
||||||
loaded = 0; /* correct the count; ugly but ... */
|
l += r;
|
||||||
|
} while (mode != SND_PCM_MODE_STREAM || l < buffer_size);
|
||||||
|
if (l > 0) {
|
||||||
#if 0
|
#if 0
|
||||||
sleep(1);
|
sleep(1);
|
||||||
#endif
|
#endif
|
||||||
if (snd_pcm_write(pcm_handle, audiobuf, l) != l) {
|
if (mmap_flag) {
|
||||||
fprintf(stderr, "write error\n");
|
if (l != buffer_size)
|
||||||
exit(1);
|
memset(audiobuf + l, silence, buffer_size - l);
|
||||||
|
while (mmap_control->fragments[frag].data) {
|
||||||
|
switch (mmap_control->status.status) {
|
||||||
|
case SND_PCM_STATUS_PREPARED:
|
||||||
|
if (snd_pcm_channel_go(pcm_handle, SND_PCM_CHANNEL_PLAYBACK)<0) {
|
||||||
|
fprintf(stderr, "%s: unable to start playback\n", command);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SND_PCM_STATUS_RUNNING:
|
||||||
|
break;
|
||||||
|
case SND_PCM_STATUS_UNDERRUN:
|
||||||
|
playback_write_error();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: bad status (mmap) = %i\n", command, mmap_control->status.status);
|
||||||
|
}
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
memcpy(mmap_data + mmap_control->fragments[frag].addr, audiobuf, buffer_size);
|
||||||
|
mmap_control->fragments[frag].data = 1;
|
||||||
|
frag++; frag %= frags;
|
||||||
|
} else if (mode == SND_PCM_MODE_BLOCK) {
|
||||||
|
if (l != buffer_size)
|
||||||
|
memset(audiobuf + l, silence, buffer_size - l);
|
||||||
|
while (fcn_write(pcm_handle, audiobuf, buffer_size) != buffer_size)
|
||||||
|
playback_write_error();
|
||||||
|
count -= l;
|
||||||
|
} else {
|
||||||
|
char *buf = audiobuf;
|
||||||
|
while (l > 0) {
|
||||||
|
while ((r = fcn_write(pcm_handle, buf, l)) < 0) {
|
||||||
|
playback_write_error();
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
static int x = 1024*1024;
|
||||||
|
if (r > 0 && r < x) {
|
||||||
|
x = r;
|
||||||
|
printf("smallest - %i\n", x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
l -= r;
|
||||||
|
count -= r;
|
||||||
|
buf += r;
|
||||||
|
if (r < 32)
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
count -= l;
|
|
||||||
} else {
|
} else {
|
||||||
if (l == -1) {
|
if (l == -1)
|
||||||
perror(name);
|
perror(name);
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
count = 0; /* Stop */
|
count = 0; /* Stop */
|
||||||
}
|
}
|
||||||
} /* while (count) */
|
} /* while (count) */
|
||||||
|
fcn_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* captureing raw data, this proc handels WAVE files and .VOCs (as one block) */
|
/* captureing raw data, this proc handels WAVE files and .VOCs (as one block) */
|
||||||
|
@ -1069,23 +1251,64 @@ void capture_go(int fd, int loaded, u_long count, int rtype, char *name)
|
||||||
u_long c;
|
u_long c;
|
||||||
|
|
||||||
header(rtype, name);
|
header(rtype, name);
|
||||||
|
format_change = 1;
|
||||||
set_format();
|
set_format();
|
||||||
|
|
||||||
while (count) {
|
while (count) {
|
||||||
c = count;
|
c = count;
|
||||||
if (c > buffer_size)
|
if (mmap_flag) {
|
||||||
c = buffer_size;
|
while (!mmap_control->fragments[frag].data) {
|
||||||
|
switch (mmap_control->status.status) {
|
||||||
if ((l = snd_pcm_read(pcm_handle, audiobuf, c)) > 0) {
|
case SND_PCM_STATUS_PREPARED:
|
||||||
if (write(fd, audiobuf, l) != l) {
|
if (snd_pcm_channel_go(pcm_handle, SND_PCM_CHANNEL_CAPTURE)<0) {
|
||||||
|
fprintf(stderr, "%s: unable to start capture\n", command);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SND_PCM_STATUS_RUNNING:
|
||||||
|
break;
|
||||||
|
case SND_PCM_STATUS_OVERRUN:
|
||||||
|
capture_read_error();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "%s: bad status (mmap) = %i\n", command, mmap_control->status.status);
|
||||||
|
}
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
if (c > buffer_size)
|
||||||
|
c = buffer_size;
|
||||||
|
if (write(fd, mmap_data + mmap_control->fragments[frag].addr, c) != c) {
|
||||||
perror(name);
|
perror(name);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
count -= l;
|
mmap_control->fragments[frag].data = 0;
|
||||||
}
|
frag++; frag %= frags;
|
||||||
if (l == -1) {
|
count -= c;
|
||||||
fprintf(stderr, "read error\n");
|
} else {
|
||||||
exit(-1);
|
if ((l = fcn_read(pcm_handle, audiobuf, buffer_size)) > 0) {
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
static int x = 1024*1024;
|
||||||
|
if (l < x) {
|
||||||
|
x = l;
|
||||||
|
printf("smallest - %i\n", x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (c > l)
|
||||||
|
c = l;
|
||||||
|
if (write(fd, audiobuf, c) != c) {
|
||||||
|
perror(name);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
count -= c;
|
||||||
|
}
|
||||||
|
if (l < -1) {
|
||||||
|
fprintf(stderr, "write error\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
if (l == 0)
|
||||||
|
usleep(10000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1098,7 +1321,7 @@ static void playback(char *name)
|
||||||
{
|
{
|
||||||
int fd, ofs;
|
int fd, ofs;
|
||||||
|
|
||||||
snd_pcm_flush_playback(pcm_handle);
|
fcn_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
|
||||||
if (!name || !strcmp(name, "-")) {
|
if (!name || !strcmp(name, "-")) {
|
||||||
fd = 0;
|
fd = 0;
|
||||||
name = "stdin";
|
name = "stdin";
|
||||||
|
@ -1114,12 +1337,13 @@ static void playback(char *name)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (test_au(fd, audiobuf) >= 0) {
|
if (test_au(fd, audiobuf) >= 0) {
|
||||||
|
rformat.format = SND_PCM_SFMT_MU_LAW;
|
||||||
playback_go(fd, 0, count, FORMAT_AU, name);
|
playback_go(fd, 0, count, FORMAT_AU, name);
|
||||||
goto __end;
|
goto __end;
|
||||||
}
|
}
|
||||||
if (read(fd, audiobuf + sizeof(AuHeader),
|
if (read(fd, audiobuf + sizeof(AuHeader),
|
||||||
sizeof(VocHeader) - sizeof(AuHeader)) !=
|
sizeof(VocHeader) - sizeof(AuHeader)) !=
|
||||||
sizeof(VocHeader) - sizeof(AuHeader)) {
|
sizeof(VocHeader) - sizeof(AuHeader)) {
|
||||||
fprintf(stderr, "%s: read error", command);
|
fprintf(stderr, "%s: read error", command);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -1138,6 +1362,7 @@ static void playback(char *name)
|
||||||
playback_go(fd, 0, count, FORMAT_WAVE, name);
|
playback_go(fd, 0, count, FORMAT_WAVE, name);
|
||||||
} else {
|
} else {
|
||||||
/* should be raw data */
|
/* should be raw data */
|
||||||
|
check_new_format(&rformat);
|
||||||
init_raw_data();
|
init_raw_data();
|
||||||
count = calc_count();
|
count = calc_count();
|
||||||
playback_go(fd, sizeof(WaveHeader), count, FORMAT_RAW, name);
|
playback_go(fd, sizeof(WaveHeader), count, FORMAT_RAW, name);
|
||||||
|
@ -1167,6 +1392,7 @@ static void capture(char *name)
|
||||||
isn't a problem (this can only be in 8 bit mono) */
|
isn't a problem (this can only be in 8 bit mono) */
|
||||||
if (fmt_rec_table[active_format].start)
|
if (fmt_rec_table[active_format].start)
|
||||||
fmt_rec_table[active_format].start(fd, count);
|
fmt_rec_table[active_format].start(fd, count);
|
||||||
|
check_new_format(&rformat);
|
||||||
capture_go(fd, 0, count, active_format, name);
|
capture_go(fd, 0, count, active_format, name);
|
||||||
fmt_rec_table[active_format].end(fd);
|
fmt_rec_table[active_format].end(fd);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue