17153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson/* tinycap.c
27153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**
37153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** Copyright 2011, The Android Open Source Project
47153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**
57153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** Redistribution and use in source and binary forms, with or without
67153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** modification, are permitted provided that the following conditions are met:
77153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**     * Redistributions of source code must retain the above copyright
87153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**       notice, this list of conditions and the following disclaimer.
97153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**     * Redistributions in binary form must reproduce the above copyright
107153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**       notice, this list of conditions and the following disclaimer in the
117153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**       documentation and/or other materials provided with the distribution.
127153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**     * Neither the name of The Android Open Source Project nor the names of
137153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**       its contributors may be used to endorse or promote products derived
147153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**       from this software without specific prior written permission.
157153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson**
167153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
177153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
187153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
197153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
207153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
217153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
227153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
237153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
247153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
257153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
267153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson** DAMAGE.
277153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson*/
287153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
297153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#include <tinyalsa/asoundlib.h>
307153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#include <stdio.h>
317153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#include <stdlib.h>
327153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#include <stdint.h>
337153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#include <signal.h>
34da39e0b09eb0a1b559a96e2108160d1d8dccf314Simon Wilson#include <string.h>
357153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
367153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#define ID_RIFF 0x46464952
377153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#define ID_WAVE 0x45564157
387153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#define ID_FMT  0x20746d66
397153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#define ID_DATA 0x61746164
407153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
417153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson#define FORMAT_PCM 1
427153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
437153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilsonstruct wav_header {
447153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t riff_id;
457153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t riff_sz;
467153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t riff_fmt;
477153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t fmt_id;
487153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t fmt_sz;
497153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint16_t audio_format;
507153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint16_t num_channels;
517153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t sample_rate;
527153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t byte_rate;
537153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint16_t block_align;
547153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint16_t bits_per_sample;
557153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t data_id;
567153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    uint32_t data_sz;
577153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson};
587153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
597153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilsonint capturing = 1;
607153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
61daa83291944318d8face12c780dfb69ae96b0723Simon Wilsonunsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
627153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson                            unsigned int channels, unsigned int rate,
6336ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson                            enum pcm_format format, unsigned int period_size,
64daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                            unsigned int period_count);
657153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
667153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilsonvoid sigint_handler(int sig)
677153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson{
687153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    capturing = 0;
697153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson}
707153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
717153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilsonint main(int argc, char **argv)
727153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson{
737153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    FILE *file;
747153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    struct wav_header header;
75daa83291944318d8face12c780dfb69ae96b0723Simon Wilson    unsigned int card = 0;
767153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    unsigned int device = 0;
777153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    unsigned int channels = 2;
787153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    unsigned int rate = 44100;
797153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    unsigned int bits = 16;
807153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    unsigned int frames;
81daa83291944318d8face12c780dfb69ae96b0723Simon Wilson    unsigned int period_size = 1024;
82daa83291944318d8face12c780dfb69ae96b0723Simon Wilson    unsigned int period_count = 4;
8336ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    enum pcm_format format;
847153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
857153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    if (argc < 2) {
86daa83291944318d8face12c780dfb69ae96b0723Simon Wilson        fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-c channels] "
87e44e30a90293ffebe604efea37842aff9d5da874Simon Wilson                "[-r rate] [-b bits] [-p period_size] [-n n_periods]\n", argv[0]);
887153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        return 1;
897153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    }
907153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
917153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    file = fopen(argv[1], "wb");
927153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    if (!file) {
937153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        fprintf(stderr, "Unable to create file '%s'\n", argv[1]);
947153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        return 1;
957153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    }
967153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
977153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    /* parse command line arguments */
987153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    argv += 2;
997153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    while (*argv) {
100dd88f13d9b398c132e3358c62137ff2e23f321abSimon Wilson        if (strcmp(*argv, "-d") == 0) {
1017153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson            argv++;
102daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            if (*argv)
103daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                device = atoi(*argv);
104dd88f13d9b398c132e3358c62137ff2e23f321abSimon Wilson        } else if (strcmp(*argv, "-c") == 0) {
1057153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson            argv++;
106daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            if (*argv)
107daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                channels = atoi(*argv);
108dd88f13d9b398c132e3358c62137ff2e23f321abSimon Wilson        } else if (strcmp(*argv, "-r") == 0) {
1097153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson            argv++;
110daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            if (*argv)
111daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                rate = atoi(*argv);
112dd88f13d9b398c132e3358c62137ff2e23f321abSimon Wilson        } else if (strcmp(*argv, "-b") == 0) {
1137153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson            argv++;
114daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            if (*argv)
115daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                bits = atoi(*argv);
116daa83291944318d8face12c780dfb69ae96b0723Simon Wilson        } else if (strcmp(*argv, "-D") == 0) {
117daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            argv++;
118daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            if (*argv)
119daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                card = atoi(*argv);
120daa83291944318d8face12c780dfb69ae96b0723Simon Wilson        } else if (strcmp(*argv, "-p") == 0) {
121daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            argv++;
122daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            if (*argv)
123daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                period_size = atoi(*argv);
124daa83291944318d8face12c780dfb69ae96b0723Simon Wilson        } else if (strcmp(*argv, "-n") == 0) {
125daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            argv++;
126daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            if (*argv)
127daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                period_count = atoi(*argv);
1287153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        }
129daa83291944318d8face12c780dfb69ae96b0723Simon Wilson        if (*argv)
130daa83291944318d8face12c780dfb69ae96b0723Simon Wilson            argv++;
1317153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    }
1327153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
1337153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.riff_id = ID_RIFF;
1347153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.riff_sz = 0;
1357153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.riff_fmt = ID_WAVE;
1367153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.fmt_id = ID_FMT;
1377153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.fmt_sz = 16;
1387153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.audio_format = FORMAT_PCM;
1397153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.num_channels = channels;
1407153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.sample_rate = rate;
14136ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson
14236ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    switch (bits) {
14336ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    case 32:
14436ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        format = PCM_FORMAT_S32_LE;
14536ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        break;
14636ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    case 24:
14736ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        format = PCM_FORMAT_S24_LE;
14836ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        break;
14936ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    case 16:
15036ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        format = PCM_FORMAT_S16_LE;
15136ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        break;
15236ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    default:
15336ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        fprintf(stderr, "%d bits is not supported.\n", bits);
15436ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson        return 1;
15536ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    }
15636ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson
15736ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    header.bits_per_sample = pcm_format_to_bits(format);
1587153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.byte_rate = (header.bits_per_sample / 8) * channels * rate;
1597153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.block_align = channels * (header.bits_per_sample / 8);
1607153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.data_id = ID_DATA;
1617153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
1627153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    /* leave enough room for header */
1637153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    fseek(file, sizeof(struct wav_header), SEEK_SET);
1647153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
1657153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    /* install signal handler and begin capturing */
1667153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    signal(SIGINT, sigint_handler);
167daa83291944318d8face12c780dfb69ae96b0723Simon Wilson    frames = capture_sample(file, card, device, header.num_channels,
16836ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson                            header.sample_rate, format,
169daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                            period_size, period_count);
1707153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    printf("Captured %d frames\n", frames);
1717153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
1727153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    /* write header now all information is known */
1737153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    header.data_sz = frames * header.block_align;
174da39e0b09eb0a1b559a96e2108160d1d8dccf314Simon Wilson    header.riff_sz = header.data_sz + sizeof(header) - 8;
1757153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    fseek(file, 0, SEEK_SET);
1767153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    fwrite(&header, sizeof(struct wav_header), 1, file);
1777153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
1787153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    fclose(file);
1797153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
1807153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    return 0;
1817153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson}
1827153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
183daa83291944318d8face12c780dfb69ae96b0723Simon Wilsonunsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
1847153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson                            unsigned int channels, unsigned int rate,
18536ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson                            enum pcm_format format, unsigned int period_size,
186daa83291944318d8face12c780dfb69ae96b0723Simon Wilson                            unsigned int period_count)
1877153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson{
1887153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    struct pcm_config config;
1897153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    struct pcm *pcm;
1907153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    char *buffer;
1917153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    unsigned int size;
1927153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    unsigned int bytes_read = 0;
1937153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
1947153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    config.channels = channels;
1957153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    config.rate = rate;
196daa83291944318d8face12c780dfb69ae96b0723Simon Wilson    config.period_size = period_size;
197daa83291944318d8face12c780dfb69ae96b0723Simon Wilson    config.period_count = period_count;
19836ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    config.format = format;
199621047309242d04a6186230e7a337de8642ec754Simon Wilson    config.start_threshold = 0;
200621047309242d04a6186230e7a337de8642ec754Simon Wilson    config.stop_threshold = 0;
201621047309242d04a6186230e7a337de8642ec754Simon Wilson    config.silence_threshold = 0;
2027153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
203daa83291944318d8face12c780dfb69ae96b0723Simon Wilson    pcm = pcm_open(card, device, PCM_IN, &config);
2047153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    if (!pcm || !pcm_is_ready(pcm)) {
2057153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        fprintf(stderr, "Unable to open PCM device (%s)\n",
2067153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson                pcm_get_error(pcm));
2077153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        return 0;
2087153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    }
2097153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
2109673f5717d824137d64320d0bc98a6461a9383a8Simon Wilson    size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
2117153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    buffer = malloc(size);
2127153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    if (!buffer) {
2137153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        fprintf(stderr, "Unable to allocate %d bytes\n", size);
2147153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        free(buffer);
2157153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        pcm_close(pcm);
2167153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        return 0;
2177153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    }
2187153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
21936ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate,
22036ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson           pcm_format_to_bits(format));
2217153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
2227153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    while (capturing && !pcm_read(pcm, buffer, size)) {
2237153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        if (fwrite(buffer, 1, size, file) != size) {
2247153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson            fprintf(stderr,"Error capturing sample\n");
2257153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson            break;
2267153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        }
2277153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson        bytes_read += size;
2287153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    }
2297153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
2307153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    free(buffer);
2317153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson    pcm_close(pcm);
23236ea2d824e5d8af550c139da9da20e73f82a9ae1Simon Wilson    return pcm_bytes_to_frames(pcm, bytes_read);
2337153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson}
2347153bffb805359a82f7857889e82bdcc5ff0afd8Simon Wilson
235