123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- /*
- * Copyright 2017 Yann Weber
- *
- * This file is part of SndPipe.
- *
- * SndPipe is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * any later version.
- *
- * SndPipe is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with SndPipe. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include <unistd.h>
- #include <stdio.h>
- #include <getopt.h>
- #include <errno.h>
-
- #ifdef SDL2
- #include <SDL2/SDL.h>
- #else
- #include <SDL/SDL.h>
- #pragma GCC error "Not supported yet :'("
- #endif
-
- #define SNDPIPE_LONG_OPT {\
- {"freq", required_argument, 0, 'f'},\
- {"signed", no_argument, 0, 'S'},\
- {"bit-size", required_argument, 0, 'B'},\
- {"endianness", required_argument, 0, 'E'},\
- {"float", no_argument, 0, 'F'},\
- {"channels", required_argument, 0, 'c'},\
- {"samples", required_argument, 0, 's'},\
- {"output", required_argument, 0, 'o'},\
- {"no-sound", no_argument, 0, 'N'},\
- {"verbose", no_argument, 0, 'v'},\
- {"help", no_argument, 0, 'h'},\
- {0, 0, 0, 0}\
- }
- #define SNDPIPE_SHORT_OPT "f:SB:E:Fc:s:o:Nvh"
- #define SNDPIPE_OPT_HELP {\
- {"Input frequencie (default is 48000)", "FREQ"},\
- {"If given signed numbers are expected (default for 32 bits)", NULL},\
- {"Number of bits per number. One of : 32, 16 and 8 (integers only)",\
- "BIT_COUNT"},\
- {"Number endianess. Accepted values are : LSB, MSB and SYS (system's \
- native byte order)", "BYTEORDER"},\
- {"If given, floating point numbers are excepted instead of intergers\
- (32 bits only)",\
- NULL},\
- {"Channels count. 1 for mono, 2 for stereo, ...", "COUNT"},\
- {"Samples per audioframe. Default value is 4096", "INT"},\
- {"Output filename. STDOUT if '-' given", "FILENAME"},\
- {"Don't play sound on soundcard using SDL", NULL},\
- {"Display informations on stderr when given", NULL},\
- {"Print this help and exit", NULL},\
- {"", NULL}\
- }
-
- #define SNDPIPE_UNSIGNED 0
- #define SNDPIPE_SIGNED 1
-
- #define SNDPIPE_ESYS 0
- #define SNDPIPE_ELSB 2
- #define SNDPIPE_EMSB 4
-
- #define SNDPIPE_BSZ_8 0
- #define SNDPIPE_BSZ_16 8
- #define SNDPIPE_BSZ_32 16
-
- #define SNDPIPE_INT32 0
- #define SNDPIPE_FLOAT32 32
-
- #define SNDPIPE_SDL_FMT {\
- AUDIO_U8,\
- AUDIO_S8,\
- 0,\
- 0,\
- 0,\
- 0,\
- 0,\
- 0,\
- AUDIO_U16SYS,\
- AUDIO_S16SYS,\
- AUDIO_U16LSB,\
- AUDIO_S16LSB,\
- AUDIO_U16MSB,\
- AUDIO_S16MSB,\
- 0,\
- 0,\
- AUDIO_S32SYS,\
- AUDIO_F32SYS,\
- AUDIO_S32LSB,\
- AUDIO_F32LSB,\
- AUDIO_S32MSB,\
- AUDIO_F32MSB\
- }
-
- static int VERBOSITY = 0;
- static int SILENT = 0;
-
- void usage()
- {
- static struct option opts[] = SNDPIPE_LONG_OPT;
- static char *help[][2] = SNDPIPE_OPT_HELP;
- size_t i;
- printf("Usage : generator | sndpipe [OPTIONS]\n");
- printf("or : sndpipe [OPTIONS] < file\n");
- printf("\t\n");
- printf("Options list\n");
- i=0;
- while(opts[i].name)
- {
- printf("\t-%c, --%s", opts[i].val, opts[i].name);
- if(opts[i].has_arg == required_argument)
- {
- printf("=%s\n",
- help[i][1]?help[i][1]:"ARG");
- }
- else if(opts[i].has_arg == optional_argument)
- {
- printf("[=%s]\n",
- help[i][1]?help[i][1]:"ARG");
- }
- else
- {
- printf("\n");
- }
- printf("\t\t%s\n\n", help[i][0]);
- i++;
- }
- }
-
-
-
- void audio_cllbck(void *udata, Uint8 *stream, int len)
- {
- int ret;
- while(len)
- {
- if((ret = read(0, stream, len)) == -1)
- {
- perror("Error reading stdin");
- exit(1);
- }
-
- if (ret == 0)
- {
- fprintf(stderr, "Stdin EOF... Exiting...\n");
- *(int*)udata = 0;
- break;
- }
-
- len -= ret;
- }
- return;
- }
-
- int main(int argc, char **argv)
- {
- static struct option long_opts[] = SNDPIPE_LONG_OPT;
- static SDL_AudioFormat opt_fmt[] = SNDPIPE_SDL_FMT;
- SDL_AudioSpec want, have;
- SDL_AudioDeviceID dev;
- int running, c, opt_i, ret, fmt_idx;
- short err;
-
- SDL_memset(&want, 0, sizeof(want));
-
- want.freq = 48000;
- want.format = AUDIO_U8;
- want.channels = 2;
- want.samples = 4096;
- want.callback = audio_cllbck;
- want.userdata = &running;
-
- fmt_idx = 0;
-
- while(1)
- {
-
- c = getopt_long(argc, argv, SNDPIPE_SHORT_OPT, long_opts, &opt_i);
- if(c == -1)
- {
- break;
- }
- switch(c)
- {
- case 'v':
- VERBOSITY++;
- break;
- case 'f':
- want.freq = atoi(optarg);
- break;
- case 'S':
- fmt_idx |= SNDPIPE_SIGNED;
- break;
- case 'B':
- switch(ret = atoi(optarg))
- {
- case 8:
- fmt_idx |= SNDPIPE_BSZ_8;
- break;
- case 16:
- fmt_idx |= SNDPIPE_BSZ_16;
- break;
- case 32:
- fmt_idx |= SNDPIPE_BSZ_32;
- break;
- default:
- fprintf(stderr, "\
- Invalid bits count %d\n", ret);
- err = 1;
- break;
- }
- break;
- case 'E':
- if( !strncmp("LSB", optarg, 4)\
- || !strncmp("lsb", optarg, 4))
- {
- fmt_idx |= SNDPIPE_ELSB;
- }
- else if(!strncmp("MSB", optarg, 4)\
- || !strncmp("msb", optarg, 4))
- {
- fmt_idx |= SNDPIPE_EMSB;
- }
- else if(!strncmp("SYS", optarg, 4)\
- || !strncmp("sys", optarg, 4))
- {
- fmt_idx |= SNDPIPE_ESYS;
- }
- else
- {
- fprintf(stderr, "\
- Invalid endianness '%s'\n", optarg);
- err = 1;
- }
- break;
- case 'F':
- fmt_idx |= SNDPIPE_FLOAT32;
- break;
- case 'c':
- want.channels = atoi(optarg);
- if(want.channels < 1)
- {
- fprintf(stderr, "Invalid channel count \
- %d\n", want.channels);
- err = 1;
- }
- break;
- case 's':
- want.samples = atoi(optarg);
- break;
- case 'o':
- fprintf(stderr, "\
- Ouptut file not implemented yet :'(\n");
- break;
- case 'N':
- SILENT = 1;
- break;
- case 'h':
- usage();
- exit(0);
- default:
- /* ?? */
- err = 1;
-
- }
- }
-
- if(err)
- {
- usage();
- exit(1);
- }
-
- if((fmt_idx & (SNDPIPE_BSZ_32 | SNDPIPE_SIGNED))\
- == (SNDPIPE_BSZ_32| SNDPIPE_SIGNED))
- {
- fmt_idx &= 0xFF - SNDPIPE_SIGNED;
- }
- if(fmt_idx & SNDPIPE_FLOAT32)
- {
- if(!(fmt_idx & SNDPIPE_BSZ_32))
- {
- fprintf(stderr, "Floats only supported for 32 bits.\n\n");
- usage();
- exit(1);
- }
- fmt_idx &= 0xFF - SNDPIPE_FLOAT32;
- fmt_idx |= 1; //correcting index for float32
- }
- if(fmt_idx & (SNDPIPE_ELSB | SNDPIPE_EMSB) \
- && !(fmt_idx & (SNDPIPE_BSZ_16 | SNDPIPE_BSZ_32)))
- {
- fprintf(stderr,
- "Specifying endianness is not supported for 8-bit\n\n");
- usage();
- exit(1);
- }
- if(fmt_idx > 21)
- {
- fprintf(stderr, "Fatal error : invalid format\n\n");
- exit(2);
- }
- if(err)
- {
- fprintf(stderr, "\n");
- exit(1);
- }
- want.format = opt_fmt[fmt_idx];
-
- if(!SILENT)
- {
- if(SDL_Init(SDL_INIT_AUDIO ) <0 )
- {
- fprintf(stderr,
- "Unable to initialize SDL : '%s'\n", SDL_GetError());
- return 1;
- }
-
- dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
- if(dev == 0)
- {
- fprintf(stderr,
- "Failed to open an audio device : '%s'\n",
- SDL_GetError());
- return 1;
- }
- }
-
- if(!SILENT)
- {
- running = 1;
- SDL_PauseAudioDevice(dev, 0); /* playing */
- while(running)
- {
- SDL_Delay(1);
- }
- SDL_Quit();
- }
- }
|