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;
}
Example #2
0
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);
}
Example #4
0
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);
}
Example #5
0
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);
}