/*
Name:sndkit.c
Copyright:gplv2
Author:rockins (ybc2084@163.com)
date:15-10-06 18:22
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 & 22k Hz
./sndkit-d/dev/dsp-c 2-r record.wav record audio IN/DEV/DSP and stereo
/sndkit-r-L record.wav record 40k audio data
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>/*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 bits,little Endian * *
#define FMT8K 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:40k * *
#define BUFF_SIZE/*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,"
"should 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,"
"should be 8 or (default 8)/n");
}
Break
Case ' F ':
if (atoi (optarg) = = 8)
SND_SPD = fmt8k; /*sampling rate:8kbps * *
else if (atoi (optarg) = = 11)
SND_SPD = fmt11k; /*smapling rate:11.025k * *
else if (atoi (optarg) = = 22)
SND_SPD = fmt22k; /*sampling rate:22.050k * *
else if (atoi (optarg) = = 44)
SND_SPD = fmt44k; /*sampling rate:44.100k * *
else if (atoi (optarg) = = 48)
SND_SPD = fmt48k; /*sampling rate:48k * *
else {
Opt_err = 1; /*error occur * *
fprintf (stderr, "wrong sampling rate,"
"should be 8,11,22,or (default 8kbps)/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 isn't full */
NWR = NRD; /*write amount to sound data file */
Else
NWR = Len-n; /*len would 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 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 (8bits), Fmt16bi TS (16bits)
* Hz-fmt8k (8000HZ), fmt16k (16000HZ), fmt22k (22000HZ),
* fmt44k (44000HZ), fmt48k (48000HZ)
* returns:
* return 0 if success, else return-1
* notes:
* parameter Setting order s Hould as:
* 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 F ailed:%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, "don't support speed%d,supported is%d/n", Hz,
Ioctl_val);
Return (-1);
}
return (0);
}
/*
* Usage ():p rint 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 8bits unsigned)/n"
"/t-f hz:indicate sampling rate,i.e,frequence (default 8kbps)/n"
"/t-l len:indicate recording sound ' s length (default 1024k)/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 & 22k hz/n"
"/T./sndkit-d/dev/dsp-c 2-r record.wav record audio in/dev/dsp and stereo/n"
"/T./sndkit-r-L record.wav record 40k audio data in record.wav/n");
}