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_hub/tinycap_hub.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;209struct pcm *pcm1;210char *buffer;211unsigned int size;212unsigned int frames;213unsigned long long bytes_read = 0;214struct timeval tv;215struct timezone tz;216long time_sec1;217long time_sec2;218long time_total;219220config.channels = channels;221config.rate = rate;222config.period_size = period_size;223config.period_count = period_count;224config.format = format;225config.start_threshold = 0;226config.stop_threshold = 0;227config.silence_threshold = 0;228229pcm = pcm_open(card, device, PCM_IN, &config);230if (!pcm || !pcm_is_ready(pcm)) {231fprintf(stderr, "Unable to open PCM device (%s)\n",232pcm_get_error(pcm));233return 0;234}235236if (device == 0)237pcm1 = pcm_open(2, 0, PCM_IN, &config);238else239printf("error: device is error");240if (!pcm1 || !pcm_is_ready(pcm1)) {241fprintf(stderr, "Unable to open PCM device %u (%s)\n",242device, pcm_get_error(pcm1));243return 0;244}245246pcm_prepare(pcm);247pcm_prepare(pcm1);248249size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));250buffer = malloc(size);251if (!buffer) {252fprintf(stderr, "Unable to allocate %d bytes\n", size);253free(buffer);254pcm_close(pcm);255pcm_close(pcm1);256return 0;257}258259if (prinfo) {260printf("Capturing sample: %u ch, %u hz, %u bit\n", channels, rate,261pcm_format_to_bits(format));262}263264gettimeofday(&tv, &tz);265time_sec1 = tv.tv_sec;266while (capturing && !pcm_read(pcm, buffer, size)) {267if (fwrite(buffer, 1, size, file) != size) {268fprintf(stderr,"Error capturing sample\n");269break;270}271gettimeofday(&tv, &tz);272time_sec2 = tv.tv_sec;273time_total = time_sec2 - time_sec1;274if (time_total >= (loop_seconds)) {275printf("time_total:%ld, loop_seconds:%d\n",276time_total, loop_seconds);277break;278}279bytes_read += size;280}281frames = pcm_bytes_to_frames(pcm, bytes_read);282free(buffer);283pcm_close(pcm);284pcm_close(pcm1);285return frames;286}287288289290