Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/tinyalsa/tinycap.c
Views: 3959
/* tinycap.c1**2** Copyright 2011, The Android Open Source Project3**4** Redistribution and use in source and binary forms, with or without5** modification, are permitted provided that the following conditions are met:6** * Redistributions of source code must retain the above copyright7** notice, this list of conditions and the following disclaimer.8** * Redistributions in binary form must reproduce the above copyright9** notice, this list of conditions and the following disclaimer in the10** documentation and/or other materials provided with the distribution.11** * Neither the name of The Android Open Source Project nor the names of12** its contributors may be used to endorse or promote products derived13** from this software without specific prior written permission.14**15** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND16** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE19** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER22** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH25** DAMAGE.26*/2728#include <tinyalsa/asoundlib.h>29#include <stdio.h>30#include <stdlib.h>31#include <stdint.h>32#include <signal.h>33#include <string.h>3435#define ID_RIFF 0x4646495236#define ID_WAVE 0x4556415737#define ID_FMT 0x20746d6638#define ID_DATA 0x617461643940#define FORMAT_PCM 14142struct wav_header {43uint32_t riff_id;44uint32_t riff_sz;45uint32_t riff_fmt;46uint32_t fmt_id;47uint32_t fmt_sz;48uint16_t audio_format;49uint16_t num_channels;50uint32_t sample_rate;51uint32_t byte_rate;52uint16_t block_align;53uint16_t bits_per_sample;54uint32_t data_id;55uint32_t data_sz;56};5758int loop_seconds = 0;59int capturing = 1;60int prinfo = 1;6162unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,63unsigned int channels, unsigned int rate,64enum pcm_format format, unsigned int period_size,65unsigned int period_count);6667void sigint_handler(int sig)68{69capturing = 0;70}7172int main(int argc, char **argv)73{74FILE *file;75struct wav_header header;76unsigned int card = 0;77unsigned int device = 0;78unsigned int channels = 2;79unsigned int rate = 44100;80unsigned int bits = 16;81unsigned int frames;82unsigned int period_size = 1024;83unsigned int period_count = 4;84enum pcm_format format;85int no_header = 0;8687if (argc < 2) {88fprintf(stderr, "Usage: %s {file.wav | --} [-D card] [-d device] [-c channels] "89"[-t seconds] [-r rate] [-b bits] [-p period_size] [-n n_periods]\n\n"90"Use -- for filename to send raw PCM to stdout\n", argv[0]);91return 1;92}9394if (strcmp(argv[1],"--") == 0) {95file = stdout;96prinfo = 0;97no_header = 1;98} else {99file = fopen(argv[1], "wb");100if (!file) {101fprintf(stderr, "Unable to create file '%s'\n", argv[1]);102return 1;103}104}105106/* parse command line arguments */107argv += 2;108while (*argv) {109if (strcmp(*argv, "-d") == 0) {110argv++;111if (*argv)112device = atoi(*argv);113} else if (strcmp(*argv, "-c") == 0) {114argv++;115if (*argv)116channels = atoi(*argv);117} else if (strcmp(*argv, "-r") == 0) {118argv++;119if (*argv)120rate = atoi(*argv);121} else if (strcmp(*argv, "-b") == 0) {122argv++;123if (*argv)124bits = atoi(*argv);125} else if (strcmp(*argv, "-D") == 0) {126argv++;127if (*argv)128card = atoi(*argv);129} else if (strcmp(*argv, "-p") == 0) {130argv++;131if (*argv)132period_size = atoi(*argv);133} else if (strcmp(*argv, "-n") == 0) {134argv++;135if (*argv)136period_count = atoi(*argv);137} else if (strcmp(*argv, "-t") == 0) {138argv++;139if (*argv)140loop_seconds = atoi(*argv);141}142if (*argv)143argv++;144}145146header.riff_id = ID_RIFF;147header.riff_sz = 0;148header.riff_fmt = ID_WAVE;149header.fmt_id = ID_FMT;150header.fmt_sz = 16;151header.audio_format = FORMAT_PCM;152header.num_channels = channels;153header.sample_rate = rate;154155switch (bits) {156case 32:157format = PCM_FORMAT_S32_LE;158break;159case 24:160format = PCM_FORMAT_S24_LE;161break;162case 16:163format = PCM_FORMAT_S16_LE;164break;165default:166fprintf(stderr, "%d bits is not supported.\n", bits);167return 1;168}169170header.bits_per_sample = pcm_format_to_bits(format);171header.byte_rate = (header.bits_per_sample / 8) * channels * rate;172header.block_align = channels * (header.bits_per_sample / 8);173header.data_id = ID_DATA;174175/* leave enough room for header */176if (!no_header) {177fseek(file, sizeof(struct wav_header), SEEK_SET);178}179180/* install signal handler and begin capturing */181signal(SIGINT, sigint_handler);182frames = capture_sample(file, card, device, header.num_channels,183header.sample_rate, format,184period_size, period_count);185if (prinfo) {186printf("Captured %d frames\n", frames);187}188189/* write header now all information is known */190if (!no_header) {191header.data_sz = frames * header.block_align;192header.riff_sz = header.data_sz + sizeof(header) - 8;193fseek(file, 0, SEEK_SET);194fwrite(&header, sizeof(struct wav_header), 1, file);195}196197fclose(file);198199return 0;200}201202unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,203unsigned int channels, unsigned int rate,204enum pcm_format format, unsigned int period_size,205unsigned int period_count)206{207struct pcm_config config;208struct pcm *pcm;209char *buffer;210unsigned int size;211unsigned int frames;212unsigned long long bytes_read = 0;213struct timeval tv;214struct timezone tz;215long time_sec1;216long time_sec2;217long time_total;218219config.channels = channels;220config.rate = rate;221config.period_size = period_size;222config.period_count = period_count;223config.format = format;224config.start_threshold = 0;225config.stop_threshold = 0;226config.silence_threshold = 0;227228pcm = pcm_open(card, device, PCM_IN, &config);229if (!pcm || !pcm_is_ready(pcm)) {230fprintf(stderr, "Unable to open PCM device (%s)\n",231pcm_get_error(pcm));232return 0;233}234235size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));236buffer = malloc(size);237if (!buffer) {238fprintf(stderr, "Unable to allocate %d bytes\n", size);239free(buffer);240pcm_close(pcm);241return 0;242}243244if (prinfo) {245printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate,246pcm_format_to_bits(format));247}248249gettimeofday(&tv, &tz);250time_sec1 = tv.tv_sec;251while (capturing && !pcm_read(pcm, buffer, size)) {252if (fwrite(buffer, 1, size, file) != size) {253fprintf(stderr,"Error capturing sample\n");254break;255}256gettimeofday(&tv, &tz);257time_sec2 = tv.tv_sec;258time_total = time_sec2 - time_sec1;259if (time_total >= (loop_seconds)) {260printf("time_total:%ld, loop_seconds:%d\n",261time_total, loop_seconds);262break;263}264bytes_read += size;265}266frames = pcm_bytes_to_frames(pcm, bytes_read);267free(buffer);268pcm_close(pcm);269return frames;270}271272273274