Simple Sound Recording
/* This example reads from the default PCM device and writes to standard output for 5 seconds of data. */ /* Use the newer ALSA API */ #define ALSA_PCM_NEW_HW_PARAMS_API #include <alsa/asoundlib.h> #include <math.h> #include <unistd.h> //#define DEVICE "hw:1,0" #define DEVICE "default" / #define CH_2 1 //#define CH_4 1 float rmsValue(signed char arr[], int n) { float square = 0.0; float mean = 0.0, root = 0.0, db= 0.0; int i; // Calculate square. for (i = 0; i < n; i++) { //printf("arr[%d]=%d, pow=%f\n", i, arr[i], pow(arr[i], 2)); square += pow(arr[i], 2); } //printf("n=%d, square=%f\n", n, square); // Calculate Mean. mean = (square / (float)(n)); // Calculate Root. root = sqrt(mean); return root; } //for ARMv7 signed char complement (signed char *a) { if((*a>>7)) { *a=*a&0xEF; *a = ~(*a) + 1; *a = *a * (-1); //for ARMv7 } else { *a=*a & 0xEF; } return *a; } int main() { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; signed char *buffer; signed char *channelbuf; int i=0, j=0, k=0, m=0, n=0; #if CH_2 int channels=2; float root[2]={0}, aroot[2]={0}; #endif #if CH_4 int channels=4; float root[4]={0}, aroot[4]={0}; #endif int rate = 16000; signed char tmp=0; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, DEVICE, SND_PCM_STREAM_CAPTURE, 0); //can use "dsnoop_test", "pulghw", or others to replace "default" if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, channels); val = rate; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ #if CH_2 frames = 32; #endif #if CH_4 frames = 32 * 2; #endif snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); #if 1 /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); #if CH_2 size = frames * 4; /* 2 bytes/sample, 2 channels */ #endif #if CH_4 size = frames * 4 * 2; /* 2 bytes/sample, 2 channels */ #endif buffer = (signed char *) malloc(sizeof(signed char)*size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 5000000 / val; printf("loops=%ld, val=%d, frames=%ld, size=%d\n", loops, val, frames, size); channelbuf = (signed char *) malloc(sizeof(signed char)*size); while (loops > 0) { loops--; //memset(buffer, '0', sizeof(signed char)*size); for(m=0; m<size; m++) buffer[m]=0; rc = snd_pcm_readi(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); break; } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } #if 0 //for recording rc = write(1, buffer, size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes\n", rc); } //while #else for(j=0; j<channels; ++j) { for (i=j, k=0; i <rc ; i += channels, ++k) { memset(channelbuf, '0', sizeof(signed char)*size); for(m=0; m<size; m++) channelbuf[m]=0; tmp=complement(buffer+(i+j)); //for ARMv7 #if 0 printf("k=%3d,tmp=%4d; ",k , tmp); if ( k%channels==0) printf("\n"); #else channelbuf[k]=tmp; //printf("ch=%d, chbuf[%d]=%3d; ", j, k, channelbuf[k]); //if ( k%channels==0) // printf("\n"); #endif } root[j]=rmsValue(channelbuf, k+1); #if 0 printf("root[%d]=%f ",j, root[j]); if ( j%channels==1) printf("\n"); #endif aroot[j] += root[j]; //printf("aroot[%i]=%f\n", j, aroot[j]); } } //while #if 1 for(j=0; j<channels; j++) fprintf(stderr, "aroot[%i]=%f\n", j, aroot[j]); for(j=0; j<channels; j++) { root[j] = 10 * log10(aroot[j]); fprintf(stderr, "root[%i]=%f\n", j, root[j]); } #endif #endif snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); free(channelbuf); #endif return 0; }
Compile: gcc rec.c -o rec -lasound -lm
ref:
1.通过pcm音频数据计算分贝
2.Some typical Sound Pressure and Sound Pressure Levels
3.db-rms
4.Alsa Audio Capture by c language
沒有留言:
張貼留言