blob: 0ac0ac02f2cd14d4df15d044c2cf9a8d8cd35cee [file] [log] [blame]
/*
** Copyright 2010, The Android Open-Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <string.h>
#include "alsa_audio.h"
#define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157
#define ID_FMT 0x20746d66
#define ID_DATA 0x61746164
#define FORMAT_PCM 1
struct wav_header {
uint32_t riff_id;
uint32_t riff_sz;
uint32_t riff_fmt;
uint32_t fmt_id;
uint32_t fmt_sz;
uint16_t audio_format;
uint16_t num_channels;
uint32_t sample_rate;
uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
uint16_t block_align; /* num_channels * bps / 8 */
uint16_t bits_per_sample;
uint32_t data_id;
uint32_t data_sz;
};
int play_file(unsigned rate, unsigned channels, int fd, unsigned count)
{
struct pcm *pcm;
struct mixer *mixer;
struct pcm_ctl *ctl = NULL;
unsigned bufsize;
char *data;
unsigned flags = PCM_OUT;
if (channels == 1)
flags |= PCM_MONO;
else
flags |= PCM_STEREO;
pcm = pcm_open(flags);
if (!pcm_ready(pcm)) {
pcm_close(pcm);
return -1;
}
mixer = mixer_open();
if (mixer)
ctl = mixer_get_control(mixer,"Playback Path", 0);
bufsize = pcm_buffer_size(pcm);
data = malloc(bufsize);
if (!data) {
fprintf(stderr,"could not allocate %d bytes\n", count);
return -1;
}
while (read(fd, data, bufsize) == bufsize) {
if (pcm_write(pcm, data, bufsize))
break;
/* HACK: remove */
if (ctl) {
//mixer_ctl_select(ctl, "SPK");
ctl = 0;
}
}
pcm_close(pcm);
return 0;
}
int play_wav(const char *fn)
{
struct wav_header hdr;
unsigned rate, channels;
int fd;
fd = open(fn, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "aplay: cannot open '%s'\n", fn);
return -1;
}
if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
fprintf(stderr, "aplay: cannot read header\n");
return -1;
}
fprintf(stderr,"aplay: %d ch, %d hz, %d bit, %s\n",
hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
if ((hdr.riff_id != ID_RIFF) ||
(hdr.riff_fmt != ID_WAVE) ||
(hdr.fmt_id != ID_FMT)) {
fprintf(stderr, "aplay: '%s' is not a riff/wave file\n", fn);
return -1;
}
if ((hdr.audio_format != FORMAT_PCM) ||
(hdr.fmt_sz != 16)) {
fprintf(stderr, "aplay: '%s' is not pcm format\n", fn);
return -1;
}
if (hdr.bits_per_sample != 16) {
fprintf(stderr, "aplay: '%s' is not 16bit per sample\n", fn);
return -1;
}
return play_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
}
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr,"usage: aplay <file>\n");
return -1;
}
return play_wav(argv[1]);
}