CODE :/* Name: SndKit. c Copyright: GPLv2 Author: rockins (ybc2084@163.com) Date: 15-10-06 Description: implent raw sound record/play Run :. /SndKit [-h] [-d device] [-c channel] [-B bits] [-f hz] [-l len] <-r |-p file> E.g .: ./SndKit-h show help information ./SndKit-r record.wav record audio from microphone (/dev/dsp) ./SndKit-d/dev/dsp-p record.wav playback record.wav via/dev/dsp ./SndKit-B 8-f 22-r reacord.wav record audio in 8 bit & 22 k hz ./SndKit-d/dev/dsp-c 2-r record.wav record audio in/dev/dsp and stereo ./SndKit-r-l 40 record.wav record 40 k audio data */ # Include # Include # Include # Include # Include # Include # Include /* For OSS style sound programing */ # Define TRUE 1 # Define FALSE 0 # Define FMT8BITS AFMT_U8/* unsigned 8 bits (for almost PC )*/ # Define FMT16BITS AFMT_S16_LE/* signed 16 bits, little endian */ # Define fmt8 K 8000/* default sampling rate */ # Define FMT11K 11025/* 11,22, 44,48 are three pop rate */ # Define FMT22K 22050 # Define FMT44K 44100 # Define FMT48K 48000 # Define MONO 1 # Define STEREO 2 # Define ACT_RECORD 0 # Define ACT_PLAY 1 # Define DFT_SND_DEV "/dev/dsp" # Define DFT_SND_FMT FMT8BITS # Define DFT_SND_SPD FMT8K # Define DFT_SND_CHN MONO # Define DFT_LEN 1024/* default record length: 40 k */ # Define BUFF_SIZE 512/* buffer size: 512 Bytes */ /************** Function prototype ********************/ Void Usage (void ); Int OpenDevice (const char *, unsigned int ); Int OpenFile (const char *, unsigned int ); Int CloseDevice (unsigned int ); Int CloseFile (unsigned int ); /************* Function implementation **************/ Int main (int argc, char * argv []) { Unsigned int snd_fmt = DFT_SND_FMT;/* sound format, bits */ Unsigned int snd_chn = DFT_SND_CHN;/* sound channel number */ Unsigned int snd_spd = DFT_SND_SPD;/* sound speed, frequency */ Unsigned char * s_file = NULL;/* file hold sound data */ Unsigned char * snd_device = DFT_SND_DEV;/* sound device */ Unsigned int recd_or_play = ACT_PLAY;/* flag (default play )*/ Unsigned char buff [BUFF_SIZE];/* sound buffer */ Unsigned long len = DFT_LEN * 1024;/* record or play length (k )*/ Int snd_fd;/* sound device descriptor */ Int s_fd;/* sound data file descrit */ Ssize_t n;/* bytes already in or out */ Ssize_t nRD;/* bytes readin */ Ssize_t nWR;/* bytes write out */ Unsigned int opt_chr;/* hold cli option */ Unsigned int opt_err = FALSE;/* indicate whether parse option error */ /* Parse cli option via getopt routine */ Optind = 0;/* set optindex to 0 */ While (opt_chr = getopt (argc, argv, "hd: c: B: f: l: r: p :"))! =-1 ){ Switch (opt_chr ){ Case 'H ': Usage (); Return (0);/* return, 0 denote success */ Break; Case 'D ': Snd_device = optarg;/* sound device name */ Break; Case 'C ': If (atoi (optarg) = 1)/* select channel number */ Snd_chn = MONO; Else if (atoi (optarg) = 2) Snd_chn = STEREO; Else { Opt_err = 1;/* error occur */ Fprintf (stderr, "wrong channel setting ," "Shoshould be 1 or 2 (default 1, MONO) \ n "); } Break; Case 'B ': If (atoi (optarg) = 8)/* select data bit */ Snd_fmt = FMT8BITS; Else if (atoi (optarg) = 16) Snd_fmt = FMT16BITS; Else { Opt_err = 1;/* error occur */ Fprintf (stderr, "wrong bits setting ," "Shocould be 8 or 16 (default 8) \ n "); } Break; Case 'F ': If (atoi (optarg) = 8) Snd_spd = FMT8K;/* sampling rate: 8 kbps */ Else if (atoi (optarg) = 11) Snd_spd = FMT11K;/* smapling rate: 11.025 k */ Else if (atoi (optarg) = 22) Snd_spd = FMT22K;/* sampling rate: 22.050 k */ Else if (atoi (optarg) = 44) Snd_spd = FMT44K;/* sampling rate: 44.100 k */ Else if (atoi (optarg) = 48) Snd_spd = FMT48K;/* sampling rate: 48 k */ Else { Opt_err = 1;/* error occur */ Fprintf (stderr, "wrong sampling rate ," "Shoshould be 8, 11, 22, or 44 (default 8 kbps) \ n "); } Break; Case 'l ': Len = atoi (optarg) * 1024;/* record length (k )*/ Break; Case 'r ': Recd_or_play = ACT_RECORD; S_file = optarg;/* file to record sound */ Break; Case 'p ': Recd_or_play = ACT_PLAY; S_file = optarg;/* file to play sound */ Break; Case '? ': Opt_err = 1; Fprintf (stderr, "unknown option: % c \ n", optopt ); Break; Default: Opt_err = 1; Fprintf (stderr, "getopt error: % d \ n", opterr ); Break; } } /* Check if cli option parsed right */ If (opt_err | argc <2 ){ Fprintf (stderr, "parse command option failed !!! \ N" "Run./SndKit-h for help \ n "); Return (-1 ); } /* Open device */ If (snd_fd = OpenDevice (snd_device, recd_or_play) <0 ){ Fprintf (stderr, "cannot open device % s: % s \ n", snd_device, Strerror (errno )); Return (-1 ); } /* Open sound data file */ If (s_fd = OpenFile (s_file, recd_or_play) <0 ){ Fprintf (stderr, "cannot open sound file % s: % s \ n", s_file, Strerror (errno )); Return (-1 ); } /* Set sound format */ If (SetFormat (snd_fd, snd_fmt, snd_chn, snd_spd) <0 ){ Fprintf (stderr, "cannot set % s in bit % d, channel % d, speed % d \ n ", Snd_device, snd_fmt, snd_chn, snd_spd ); Return (-1 ); } /* Do real action: record or playback */ If (recd_or_play = ACT_RECORD) {/* record sound into data file */ N = 0; While (n <len ){ NRD = 0;/* amount read from sound device */ If (nRD = read (snd_fd, buff, BUFF_SIZE) <0 ){ Perror ("read sound device failed "); Return (-1 ); } If (n + nRD <= len)/* the len is not full */ NWR = nRD;/* write amount to sound data file */ Else NWR = len-n;/* len will be overflow */ Unsigned long old_nWR = nWR;/* s hold nWR's old value */ Unsigned long t = 0L;/* temp counter */ While (nWR> 0 ){ If (t = write (s_fd, buff, nWR) <0 ){ Perror ("write sound data file failed "); Return (-1 ); } NWR-= t; } N + = old_nWR; } } Else if (recd_or_play = ACT_PLAY) {/* write sound data to device */ While (TRUE ){ NRD = 0L;/* read amount from sound device */ If (nRD = read (s_fd, buff, BUFF_SIZE) <0 ){ Perror ("read sound data file failed "); Return (-1 ); } Else if (nRD = 0) {/* nRD = 0 means all sound stream output */ Printf ("sound data play complete! \ N "); Exit (0 ); } NWR = nRD; While (nWR> 0) {/* write into device */ If (n = write (snd_fd, buff, nWR) <0 ){ Perror ("write sound device file failed "); Return (-1 ); } NWR-= n; } } } /* Close the sound device and sound data file */ CloseDevice (snd_fd ); CloseFile (s_fd ); Return (0 ); } /* * OpenDevice (): open sound device * Params: * Dev_name -- device name, such as/dev/dsp * Flag -- flag (ACT_RECORD or ACT_PLAY) * Returns: * File descriptor of sound device if sucess *-1 if failed */ Int OpenDevice (const char * dev_name, unsigned int flag) { Int dev_fd; /* Open sound device */ If (flag = ACT_RECORD ){ If (dev_fd = open (dev_name, O_RDONLY) <0 ){ Return (-1 ); } } Else if (flag = ACT_PLAY ){ If (dev_fd = open (dev_name, O_WRONLY) <0 ){ Return (-1 ); } } Return (dev_fd ); } /* * CloseDevice (): close the sound device * Params: * Dev_fd -- the sound device's file descriptor * Returns: * 0 if success *-1 if error occured */ Int CloseDevice (unsigned int dev_fd) { Return (close (dev_fd )); } /* * OpenFile (): open sound data file * Params: * File_name -- file name,e.g,record.wav * Flag -- flag (ACT_RECORD or ACT_PLAY) * Returns: * File descriptor of sound data file if sucess *-1 if failed */ Int OpenFile (const char * file_name, unsigned int flag) { Int file_fd; /* Open sound data file */ If (flag = ACT_RECORD ){ If (file_fd = open (file_name, O_WRONLY) <0 ){ Return (-1 ); } } Else if (flag = ACT_PLAY ){ If (file_fd = open (file_name, O_RDONLY) <0 ){ Return (-1 ); } } Return (file_fd ); } /* * CloseFile (): close the sound data file * Params: * File_fd -- the sound data file's descriptor * Returns: * 0 if success *-1 if error occured */ Int CloseFile (unsigned int file_fd) { Return (close (file_fd )); } /* * SetFormat (): Set Record and Playback format * Params; * Fd -- device file descriptor * Chn -- channel (MONO or STEREO) * Bits -- FMT8BITS (8 bits), FMT16BITS (16 bits) * Hz -- FMT8K (8000 HZ), FMT16K (16000 HZ), FMT22K (22000 HZ ), * FMT44K (44000 HZ), FMT48K (48000 HZ) * Returns: * Return 0 if success, else return-1 * Notes: * Parameter setting order shoshould be like: * 1. sample format (number of bits) * 2. number of channels (mono or stereo) * 3. sampling rate (speed) */ Int SetFormat (unsigned int fd, unsigned int bits, unsigned int chn, Unsigned int hz) { Int ioctl_val; /* Set bit format */ Ioctl_val = bits; If (ioctl (fd, SNDCTL_DSP_SETFMT, & ioctl_val) =-1 ){ Fprintf (stderr, "Set fmt to bit % d failed: % s \ n", bits, Strerror (errno )); Return (-1 ); } If (ioctl_val! = Bits ){ Fprintf (stderr, "do not support bit % d, supported % d \ n", bits, Ioctl_val ); Return (-1 ); } /* Set channel */ Ioctl_val = chn; If (ioctl (fd, SNDCTL_DSP_CHANNELS, & ioctl_val) =-1 ){ Fprintf (stderr, "Set Audio Channels % d failed: % s \ n", chn, Strerror (errno )); Return (-1 ); } If (ioctl_val! = Chn ){ Fprintf (stderr, "do not support channel % d, supported % d \ n", chn, Ioctl_val ); Return (-1 ); } /* Set speed */ Ioctl_val = hz; If (ioctl (fd, SNDCTL_DSP_SPEED, & ioctl_val) =-1 ){ Fprintf (stderr, "Set speed to % d failed: % s \ n", hz, Strerror (errno )); Return (-1 ); } If (ioctl_val! = Hz ){ Fprintf (stderr, "do not support speed % d, supported is % d \ n", hz, Ioctl_val ); Return (-1 ); } Return (0 ); } /* * Usage (): print help information * Params :( none) * Returns :( none) */ Void Usage (void) { Printf ("Run :. /SndKit [-h] [-d device] [-c channel] [-B bits] [-f hz] [-l len] <-r |-p file> \ n" "Description: implent raw sound record/play \ n" "option: \ n" "\ T-h: print help informations \ n" "\ T-d device: assign sound device to record or playback (default/dev/dsp) \ n" "\ T-c channel: indicate in MONO or STEREO channel (default MONO) \ n" "\ T-B bits: assign sampling bits depth (default 8 bits unsigned) \ n" "\ T-f hz: indicate sampling rate, I. e, frequence (default 8 kbps) \ n" "\ T-l len: indicate recording sound's length (default 1024 k) \ n" "\ T-r |-p file: indicate record in or playback (no default, must give out explicitly) \ n" "E.g.: \ n" "\ T./SndKit-h show help information \ n" "\ T./SndKit-r record.wav record audio from microphone (/dev/dsp) \ n" "\ T./SndKit-d/dev/dsp-p record.wav playback record.wav via/dev/dsp \ n" "\ T./SndKit-B 8-f 22-r reacord.wav record audio in 8 bit & 22 k hz \ n" "\ T./SndKit-d/dev/dsp-c 2-r record.wav record audio in/dev/dsp and stereo \ n" "\ T./SndKit-r-l 40 record.wav record 40 k audio data in record.wav \ n "); } |