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