bool AudioRecordingLocal::doPrepare(AudioHardware::SamplingRate samplingRate, int samplesInOneGo) { releaseHw(); struct pcm_config config; memset(&config, 0, sizeof(config)); config.channels = 2; config.rate = samplingRate; config.period_size = 1024; config.period_count = 32; config.format = PCM_FORMAT_S16_LE; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; mPcmHandle = pcm_open(mHwId, 0, PCM_IN, &config); if (!mPcmHandle || !pcm_is_ready(mPcmHandle)) { LOGE("Unable to open PCM device(%d) (%s)\n", mHwId, pcm_get_error(mPcmHandle)); return false; } mSamples = samplesInOneGo; mSizes = samplesInOneGo * 4; // stereo, 16bit mBufferSize = pcm_get_buffer_size(mPcmHandle); LOGD("buffer size %d, read size %d", mBufferSize, mSizes); return true; }
audio_t * audio_new(audio_config_t *cfg, audio_device_t *device) { struct pcm_config config; struct pcm *pcm; audio_t *c; if (cfg->bits != 16 && cfg->bits != 24 && cfg->bits != 32) { errno = EINVAL; return NULL; } config.channels = cfg->channels; config.rate = cfg->rate; config.period_size = 1024; config.period_count = 4; config.format = cfg->bits == 16 ? PCM_FORMAT_S16_LE : cfg->bits == 32 ? PCM_FORMAT_S32_LE : PCM_FORMAT_S24_LE; config.start_threshold = config.stop_threshold = config.silence_threshold = 0; if ((pcm = pcm_open(device->card, device->device, device->playback ? PCM_OUT : PCM_IN, &config)) == NULL || ! pcm_is_ready(pcm)) { fprintf(stderr, "Failed to open: %s\n", pcm_get_error(pcm)); return NULL; } c = fatal_malloc(sizeof(*c)); c->pcm = pcm; c->cfg = *cfg; c->dev = *device; c->buffer_size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); return c; }
void play_sample(FILE *file, unsigned int device, unsigned int channels, unsigned int rate, unsigned int bits) { struct pcm_config config; struct pcm *pcm0; char *buffer; int size; int num_read; /* channels = 2,period_size = 8092; buffer_size = 8092*4 = 32k channels = 4, period_size = 4096, buffer_size = 4096*8 = 32k channels = 4, period_size = 2048, buffer_size = 2048*8 = 16k channels = 4, period_size = 1024, buffer_size = 1024*8 = 8k */ config.channels = 4; config.rate = rate; config.period_size = 1024;//4096;//2048 config.period_count = 1; if (bits == 32) config.format = PCM_FORMAT_S32_LE; else if (bits == 16) config.format = PCM_FORMAT_S16_LE; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; /*0 is audiocodec, 1 is hdmiaudio, 2 is spdif*/ pcm0 = pcm_open(1, device, PCM_OUT, &config); if (!pcm0 || !pcm_is_ready(pcm0)) { fprintf(stderr, "Unable to open PCM device %u (%s)\n", device, pcm_get_error(pcm0)); return; } size = pcm_get_buffer_size(pcm0); buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %d bytes\n", size); free(buffer); pcm_close(pcm0); return; } size =size; printf("hx-Playing sample:size:%d, %u ch, %u hz, %u bit\n", size, channels, rate, bits); do { num_read = fread(buffer, 1, size, file); if (num_read > 0) { if (pcm_write(pcm0, buffer, num_read)) { fprintf(stderr, "Error playing sample\n"); break; } } } while (num_read > 0); free(buffer); pcm_close(pcm0); }
unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels, unsigned int rate, enum pcm_format format, unsigned int period_size, unsigned int period_count) { struct pcm_config config; struct pcm *pcm; char *buffer; unsigned int size; unsigned int bytes_read = 0; memset(&config, 0, sizeof(config)); config.channels = channels; config.rate = rate; config.period_size = period_size; config.period_count = period_count; config.format = format; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; pcm = pcm_open(card, device, PCM_IN, &config); if (!pcm || !pcm_is_ready(pcm)) { fprintf(stderr, "Unable to open PCM device (%s)\n", pcm_get_error(pcm)); return 0; } size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %d bytes\n", size); free(buffer); pcm_close(pcm); return 0; } printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate, pcm_format_to_bits(format)); while (capturing && !pcm_read(pcm, buffer, size)) { if (fwrite(buffer, 1, size, file) != size) { fprintf(stderr,"Error capturing sample\n"); break; } bytes_read += size; } free(buffer); pcm_close(pcm); return pcm_bytes_to_frames(pcm, bytes_read); }
unsigned int capture_sample(FILE *file, unsigned int device, unsigned int channels, unsigned int rate, unsigned int bits) { struct pcm_config config; struct pcm *pcm; char *buffer; unsigned int size; unsigned int bytes_read = 0; config.channels = channels; config.rate = rate; config.period_size = 1024; config.period_count = 4; if (bits == 32) config.format = PCM_FORMAT_S32_LE; else if (bits == 16) config.format = PCM_FORMAT_S16_LE; pcm = pcm_open(0, device, PCM_IN, &config); if (!pcm || !pcm_is_ready(pcm)) { fprintf(stderr, "Unable to open PCM device (%s)\n", pcm_get_error(pcm)); return 0; } size = pcm_get_buffer_size(pcm); buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %d bytes\n", size); free(buffer); pcm_close(pcm); return 0; } printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate, bits); while (capturing && !pcm_read(pcm, buffer, size)) { if (fwrite(buffer, 1, size, file) != size) { fprintf(stderr,"Error capturing sample\n"); break; } bytes_read += size; } free(buffer); pcm_close(pcm); return bytes_read / ((bits / 8) * channels); }
int play(int argc, char **argv) { int nMixer = -1, nDevice = -1; pcm_config cfg = { channels : 0, rate : 0, period_size : 1024, period_count : 4, format : PCM_FORMAT_S16_LE, start_threshold : 0, stop_threshold : 0, silence_threshold : 0, }; if (argc == 6) { nMixer = atoi(argv[2]); nDevice = atoi(argv[3]); cfg.rate = atoi(argv[4]); cfg.channels = atoi(argv[5]); } if (argc != 6 || nMixer < 0 || nMixer > 7 || nDevice < 0 || cfg.rate <= 0 || cfg.channels <= 0 || cfg.channels > 2) { printf("Usage: ainfo play <card number> <device number> <rate> <channels>\n" "where <card number> is between 0 and 7\n" "<device number> is the device to play on\n" "<rate> is the sampling rate\n" "<channels> is either 1 or 2\n" "NOTE The file to be played is read from stdin\n"); return 0; } pcm *p = pcm_open(nMixer, nDevice, PCM_OUT, &cfg); if (!pcm_is_ready(p)) { printf("Device not ready. Probably due to invalid parameters."); pcm_close(p); return -1; } unsigned bufsize = pcm_get_buffer_size(p); char *data = new char[bufsize]; if (!data) { printf("Could not allocate %d bytes.\n", bufsize); return -1; } while (read(0, data, bufsize) == bufsize) { printf("."); if (pcm_write(p, data, bufsize)) break; } printf("\b.\nFinished.\n"); delete [] data; pcm_close(p); return 0; } int main(int argc, char **argv) { if (argc >= 2) { if (!strcmp(argv[1], "list")) return list(argc, argv); else if (!strcmp(argv[1], "read")) return read(argc, argv); else if (!strcmp(argv[1], "read-range")) return read_range(argc, argv); else if (!strcmp(argv[1], "write")) return write(argc, argv); else if (!strcmp(argv[1], "write-percentage")) return write_percentage(argc, argv); else if (!strcmp(argv[1], "play")) return play(argc, argv); } printf("Usage: audiotest <command>\nwhere <command> is one of:\n" "list, read, read-range, write, write-percentage, play\n"); return 0; }
bool AudioPlayer::threadLoop() { struct pcm_config config; struct pcm *pcm = NULL; bool moreChunks = true; const struct chunk_fmt* chunkFmt = NULL; int bufferSize; const uint8_t* wavData; size_t wavLength; const struct riff_wave_header* wavHeader; if (mCurrentFile == NULL) { ALOGE("mCurrentFile is NULL"); return false; } wavData = (const uint8_t *)mCurrentFile->getDataPtr(); if (!wavData) { ALOGE("Could not access WAV file data"); goto exit; } wavLength = mCurrentFile->getDataLength(); wavHeader = (const struct riff_wave_header *)wavData; if (wavLength < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) || (wavHeader->wave_id != ID_WAVE)) { ALOGE("Error: audio file is not a riff/wave file\n"); goto exit; } wavData += sizeof(*wavHeader); wavLength -= sizeof(*wavHeader); do { const struct chunk_header* chunkHeader = (const struct chunk_header*)wavData; if (wavLength < sizeof(*chunkHeader)) { ALOGE("EOF reading chunk headers"); goto exit; } wavData += sizeof(*chunkHeader); wavLength -= sizeof(*chunkHeader); switch (chunkHeader->id) { case ID_FMT: chunkFmt = (const struct chunk_fmt *)wavData; wavData += chunkHeader->sz; wavLength -= chunkHeader->sz; break; case ID_DATA: /* Stop looking for chunks */ moreChunks = 0; break; default: /* Unknown chunk, skip bytes */ wavData += chunkHeader->sz; wavLength -= chunkHeader->sz; } } while (moreChunks); if (!chunkFmt) { ALOGE("format not found in WAV file"); goto exit; } memset(&config, 0, sizeof(config)); config.channels = chunkFmt->num_channels; config.rate = chunkFmt->sample_rate; config.period_size = mPeriodSize; config.period_count = mPeriodCount; config.start_threshold = mPeriodSize / 4; config.stop_threshold = INT_MAX; config.avail_min = config.start_threshold; if (chunkFmt->bits_per_sample != 16) { ALOGE("only 16 bit WAV files are supported"); goto exit; } config.format = PCM_FORMAT_S16_LE; pcm = pcm_open(mCard, mDevice, PCM_OUT, &config); if (!pcm || !pcm_is_ready(pcm)) { ALOGE("Unable to open PCM device (%s)\n", pcm_get_error(pcm)); goto exit; } bufferSize = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); while (wavLength > 0) { if (exitPending()) goto exit; size_t count = bufferSize; if (count > wavLength) count = wavLength; if (pcm_write(pcm, wavData, count)) { ALOGE("pcm_write failed (%s)", pcm_get_error(pcm)); goto exit; } wavData += count; wavLength -= count; } exit: if (pcm) pcm_close(pcm); mCurrentFile->release(); mCurrentFile = NULL; return false; }
void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels, unsigned int rate, unsigned int bits, unsigned int period_size, unsigned int period_count) { struct pcm_config config; struct pcm *pcm; char *buffer; int size; int num_read; memset(&config, 0, sizeof(config)); config.channels = channels; config.rate = rate; config.period_size = period_size; config.period_count = period_count; if (bits == 32) config.format = PCM_FORMAT_S32_LE; else if (bits == 16) config.format = PCM_FORMAT_S16_LE; config.start_threshold = 0; config.stop_threshold = 0; config.silence_threshold = 0; if (!sample_is_playable(card, device, channels, rate, bits, period_size, period_count)) { return; } pcm = pcm_open(card, device, PCM_OUT, &config); if (!pcm || !pcm_is_ready(pcm)) { fprintf(stderr, "Unable to open PCM device %u (%s)\n", device, pcm_get_error(pcm)); return; } size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm)); buffer = malloc(size); if (!buffer) { fprintf(stderr, "Unable to allocate %d bytes\n", size); free(buffer); pcm_close(pcm); return; } printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits); /* catch ctrl-c to shutdown cleanly */ signal(SIGINT, stream_close); do { num_read = fread(buffer, 1, size, file); if (num_read > 0) { if (pcm_write(pcm, buffer, num_read)) { fprintf(stderr, "Error playing sample\n"); break; } } } while (!close && num_read > 0); free(buffer); pcm_close(pcm); }