1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/* Copyright (C) 2008 The Android Open Source Project
2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */
3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdio.h>
5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h>
6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <fcntl.h>
7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdint.h>
8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/mman.h>
9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/ioctl.h>
10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <linux/ioctl.h>
12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define AUDIO_IOCTL_MAGIC 'a'
14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define AUDIO_START        _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned)
16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define AUDIO_STOP         _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned)
17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define AUDIO_FLUSH        _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned)
18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define AUDIO_GET_CONFIG   _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned)
19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define AUDIO_SET_CONFIG   _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned)
20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define AUDIO_GET_STATS    _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned)
21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
22e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct msm_audio_config {
23e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t buffer_size;
24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t buffer_count;
25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t channel_count;
26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t sample_rate;
27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t codec_type;
28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t unused[3];
29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project};
30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct msm_audio_stats {
32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t out_bytes;
33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    uint32_t unused[3];
34e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project};
35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint pcm_play(unsigned rate, unsigned channels,
37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project             int (*fill)(void *buf, unsigned sz, void *cookie),
38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project             void *cookie)
39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct msm_audio_config config;
41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct msm_audio_stats stats;
42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned sz, n;
43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char buf[8192];
44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int afd;
45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
46e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    afd = open("/dev/msm_pcm_out", O_RDWR);
47e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (afd < 0) {
48e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("pcm_play: cannot open audio device");
49e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
50e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
51e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
52e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if(ioctl(afd, AUDIO_GET_CONFIG, &config)) {
53e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("could not get config");
54e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
55e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
56e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
57e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    config.channel_count = channels;
58e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    config.sample_rate = rate;
59e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ioctl(afd, AUDIO_SET_CONFIG, &config)) {
60e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("could not set config");
61e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
62e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
63e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    sz = config.buffer_size;
64e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (sz > sizeof(buf)) {
65e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr,"too big\n");
66e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
67e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
68e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
69e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fprintf(stderr,"prefill\n");
70e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (n = 0; n < config.buffer_count; n++) {
71e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (fill(buf, sz, cookie))
72e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            break;
73e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (write(afd, buf, sz) != sz)
74e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            break;
75e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
76e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
77e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fprintf(stderr,"start\n");
78e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    ioctl(afd, AUDIO_START, 0);
79e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
80e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (;;) {
81e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#if 0
82e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (ioctl(afd, AUDIO_GET_STATS, &stats) == 0)
83e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            fprintf(stderr,"%10d\n", stats.out_bytes);
84e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#endif
85e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (fill(buf, sz, cookie))
86e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            break;
87e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (write(afd, buf, sz) != sz)
88e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            break;
89e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
90e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
91e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdone:
92e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(afd);
93e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
94e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
95e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
96e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/* http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
97e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
98e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define ID_RIFF 0x46464952
99e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define ID_WAVE 0x45564157
100e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define ID_FMT  0x20746d66
101e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define ID_DATA 0x61746164
102e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
103e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define FORMAT_PCM 1
104e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
105e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct wav_header {
106e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t riff_id;
107e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t riff_sz;
108e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t riff_fmt;
109e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t fmt_id;
110e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t fmt_sz;
111e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint16_t audio_format;
112e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint16_t num_channels;
113e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t sample_rate;
114e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t byte_rate;       /* sample_rate * num_channels * bps / 8 */
115e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint16_t block_align;     /* num_channels * bps / 8 */
116e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint16_t bits_per_sample;
117e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t data_id;
118e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	uint32_t data_sz;
119e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project};
120e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
121e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
122e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic char *next;
123e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic unsigned avail;
124e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
125e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint fill_buffer(void *buf, unsigned sz, void *cookie)
126e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
127e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (sz > avail)
128e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
129e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    memcpy(buf, next, sz);
130e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    next += sz;
131e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    avail -= sz;
132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
133e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
134e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
135e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectvoid play_file(unsigned rate, unsigned channels,
136e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project               int fd, unsigned count)
137e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
138e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    next = malloc(count);
139e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (!next) {
140e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr,"could not allocate %d bytes\n", count);
141e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return;
142e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
143e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (read(fd, next, count) != count) {
144e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr,"could not read %d bytes\n", count);
145e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return;
146e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
147e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    avail = count;
148e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pcm_play(rate, channels, fill_buffer, 0);
149e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
150e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
151e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint wav_play(const char *fn)
152e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
153e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	struct wav_header hdr;
154e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned rate, channels;
155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	int fd;
156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	fd = open(fn, O_RDONLY);
157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	if (fd < 0) {
158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr, "playwav: cannot open '%s'\n", fn);
159e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project		return -1;
160e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	}
161e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr, "playwav: cannot read header\n");
163e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project		return -1;
164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	}
165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fprintf(stderr,"playwav: %d ch, %d hz, %d bit, %s\n",
166e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
167e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
168e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
169e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if ((hdr.riff_id != ID_RIFF) ||
170e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        (hdr.riff_fmt != ID_WAVE) ||
171e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        (hdr.fmt_id != ID_FMT)) {
172e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr, "playwav: '%s' is not a riff/wave file\n", fn);
173e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
174e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
175e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if ((hdr.audio_format != FORMAT_PCM) ||
176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        (hdr.fmt_sz != 16)) {
177e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr, "playwav: '%s' is not pcm format\n", fn);
178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
179e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
180e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (hdr.bits_per_sample != 16) {
181e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr, "playwav: '%s' is not 16bit per sample\n", fn);
182e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
183e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
184e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
185e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    play_file(hdr.sample_rate, hdr.num_channels,
186e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project              fd, hdr.data_sz);
187e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
188e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
189e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
190e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
191e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint wav_rec(const char *fn, unsigned channels, unsigned rate)
192e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
193e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct wav_header hdr;
194e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned char buf[8192];
195e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    struct msm_audio_config cfg;
196e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned sz, n;
197e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int fd, afd;
198e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned total = 0;
199e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned char tmp;
200e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
201e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.riff_id = ID_RIFF;
202e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.riff_sz = 0;
203e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.riff_fmt = ID_WAVE;
204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.fmt_id = ID_FMT;
205e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.fmt_sz = 16;
206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.audio_format = FORMAT_PCM;
207e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.num_channels = channels;
208e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.sample_rate = rate;
209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.byte_rate = hdr.sample_rate * hdr.num_channels * 2;
210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.block_align = hdr.num_channels * 2;
211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.bits_per_sample = 16;
212e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.data_id = ID_DATA;
213e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.data_sz = 0;
214e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
215e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fd = open(fn, O_CREAT | O_RDWR, 0666);
216e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (fd < 0) {
217e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot open output file");
218e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
219e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
220e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    write(fd, &hdr, sizeof(hdr));
221e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
222e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    afd = open("/dev/msm_pcm_in", O_RDWR);
223e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (afd < 0) {
224e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot open msm_pcm_in");
225e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        close(fd);
226e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
227e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
228e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
229e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        /* config change should be a read-modify-write operation */
230e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ioctl(afd, AUDIO_GET_CONFIG, &cfg)) {
231e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot read audio config");
232e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        goto fail;
233e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
234e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
235e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    cfg.channel_count = hdr.num_channels;
236e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    cfg.sample_rate = hdr.sample_rate;
237e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ioctl(afd, AUDIO_SET_CONFIG, &cfg)) {
238e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot write audio config");
239e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        goto fail;
240e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
241e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
242e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ioctl(afd, AUDIO_GET_CONFIG, &cfg)) {
243e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot read audio config");
244e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        goto fail;
245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    sz = cfg.buffer_size;
248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fprintf(stderr,"buffer size %d x %d\n", sz, cfg.buffer_count);
249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (sz > sizeof(buf)) {
250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr,"buffer size %d too large\n", sz);
251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        goto fail;
252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
253e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
254e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ioctl(afd, AUDIO_START, 0)) {
255e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot start audio");
256e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        goto fail;
257e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
258e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fcntl(0, F_SETFL, O_NONBLOCK);
260e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fprintf(stderr,"\n*** RECORDING * HIT ENTER TO STOP ***\n");
261e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
262e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (;;) {
263e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        while (read(0, &tmp, 1) == 1) {
264e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if ((tmp == 13) || (tmp == 10)) goto done;
265e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
266e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (read(afd, buf, sz) != sz) {
267e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            perror("cannot read buffer");
268e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            goto fail;
269e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
270e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (write(fd, buf, sz) != sz) {
271e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            perror("cannot write buffer");
272e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            goto fail;
273e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
274e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        total += sz;
275e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
276e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
277e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdone:
278e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(afd);
279e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
280e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        /* update lengths in header */
281e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.data_sz = total;
282e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    hdr.riff_sz = total + 8 + 16 + 8;
283e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    lseek(fd, 0, SEEK_SET);
284e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    write(fd, &hdr, sizeof(hdr));
285e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(fd);
286e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
287e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
288e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectfail:
289e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(afd);
290e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(fd);
291e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unlink(fn);
292e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return -1;
293e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
294e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
295e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint mp3_play(const char *fn)
296e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
297e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    char buf[64*1024];
298e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int r;
299e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int fd, afd;
300e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
301e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fd = open(fn, O_RDONLY);
302e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (fd < 0) {
303e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot open mp3 file");
304e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
305e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
306e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
307e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    afd = open("/dev/msm_mp3", O_RDWR);
308e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (afd < 0) {
309e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        close(fd);
310e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        perror("cannot open mp3 output device");
311e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return -1;
312e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
313e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
314e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fprintf(stderr,"MP3 PLAY\n");
315e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    ioctl(afd, AUDIO_START, 0);
316e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
317e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (;;) {
318e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        r = read(fd, buf, 64*1024);
319e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (r <= 0) break;
320e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        r = write(afd, buf, r);
321e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (r < 0) break;
322e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
323e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
324e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(fd);
325e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    close(afd);
326e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
327e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
328e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
329e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char **argv)
330e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project{
331e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    const char *fn = 0;
332e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int play = 1;
333e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned channels = 1;
334e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned rate = 44100;
335e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
336e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    argc--;
337e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    argv++;
338e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    while (argc > 0) {
339e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (!strcmp(argv[0],"-rec")) {
340e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            play = 0;
341e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        } else if (!strcmp(argv[0],"-play")) {
342e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            play = 1;
343e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        } else if (!strcmp(argv[0],"-stereo")) {
344e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            channels = 2;
345e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        } else if (!strcmp(argv[0],"-mono")) {
346e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            channels = 1;
347e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        } else if (!strcmp(argv[0],"-rate")) {
348e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            argc--;
349e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            argv++;
350e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            if (argc == 0) {
351e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                fprintf(stderr,"playwav: -rate requires a parameter\n");
352e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                return -1;
353e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            }
354e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            rate = atoi(argv[0]);
355e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        } else {
356e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            fn = argv[0];
357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
358e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        argc--;
359e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        argv++;
360e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
362e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (fn == 0) {
363e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fn = play ? "/data/out.wav" : "/data/rec.wav";
364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
365e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
366e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (play) {
367e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        const char *dot = strrchr(fn, '.');
368e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (dot && !strcmp(dot,".mp3")) {
369e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return mp3_play(fn);
370e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        } else {
371e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            return wav_play(fn);
372e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
373e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    } else {
374e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return wav_rec(fn, channels, rate);
375e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
376e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project	return 0;
377e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
378