Skip to content

Commit 9058a59

Browse files
committed
submit all files
0 parents  commit 9058a59

23 files changed

+6305
-0
lines changed

Makefile

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
CC = /home/midas/openwrt_widora/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-gcc
2+
3+
APP = autorecord4
4+
5+
INCLUDES += -I/.
6+
INCLUDES += -I/home/midas/openwrt_widora/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/alsa-lib-1.0.28/include
7+
LDFLAGS += -L.
8+
LDFLAGS += -L/home/midas/openwrt_widora/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/alsa-lib-1.0.28/ipkg-install/usr/lib
9+
LIBS += -lasound -lm -lshine
10+
11+
$(APP): $(APP).c
12+
$(CC) $(INCLUDES) $(LDFLAGS) $(LIBS) -o $(APP) $(APP).c
13+
14+
PHONY:all
15+
all: $(APP)
16+
17+
clean:
18+
rm -rf $(APP)
19+

README

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
NOTE:
2+
1. Widora C test programs for ALSA, automatic record and playback, with options of a simple noise filter.
3+
The recorded sound wav can be saved as wav and mp3.
4+
See more notes and descriptions in respective source files.
5+
6+
2. The Makefile only gives an example for 'autorecord4' compilation, you can modify it easily for other applications.
7+
Modify INCLUDE and LIB directories according to your own setup.
8+

alsatest.c

+875
Large diffs are not rendered by default.

autorecord.c

+277
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
/*--------------------------------------------------
2+
ALSA auto. record and play test
3+
Quote from: http://blog.csdn.net/ljclx1748/article/details/8606831
4+
5+
Usage: ./autorecord
6+
It will monitor surrounding sound wave and trigger 10s recording if loud voice is sensed,
7+
then it will playback. The sound will also be saved to a raw file.
8+
9+
1. use alsamixer to adjust Capture and ADC PCM value
10+
ADC PCM 0-255 (240)
11+
Capture 0-63 (53)
12+
2. some explanation:
13+
sample: usually 8bits or 16bits, one sample data width.
14+
channel: 1-Mono. 2-Stereo
15+
frame: sizeof(one sample)*channels
16+
rate: frames per second
17+
period: Max. frame numbers hard ware can be handled each time.
18+
chunk: frames receive from/send to hard ware each time.
19+
buffer: N*periods
20+
interleaved mode:record period data frame by frame, such as frame1(Left sample,Right sample),frame2(), ......
21+
uninterleaved mode: record period data channel by channel, such as period(Left sample,Left ,left...),period(right,right...),period()...
22+
3. lib: lasound
23+
--------------------------------------------------*/
24+
25+
#include <asoundlib.h>
26+
#include <stdbool.h>
27+
#define CHECK_AVERG 2500 //--threshold value of wave amplitude
28+
29+
snd_pcm_t *pcm_handle;
30+
snd_pcm_hw_params_t *params;
31+
snd_pcm_format_t format_val;
32+
char *wave_buf; //---pointer to wave buffer
33+
int wave_buf_len; //---wave buffer length in bytes
34+
int bit_per_sample;
35+
snd_pcm_uframes_t frames;
36+
snd_pcm_uframes_t period_size; //length of period (in frames)
37+
snd_pcm_uframes_t chunk_size=32;//numbers of frames read/write to hard ware each time
38+
int chunk_byte; //length of chunk (period) (in bytes)
39+
unsigned int chanl_val,rate_val;
40+
int dir;
41+
42+
43+
//------------------- functions declaration ----------------------
44+
bool device_open( int mode);
45+
bool device_setparams();
46+
bool device_capture( int dtime );
47+
bool device_play();
48+
bool device_check_voice();
49+
50+
/*========================= MAIN ====================================*/
51+
int main(int argc,char* argv[]){
52+
int fd;
53+
int rc;
54+
55+
while(1)
56+
{
57+
58+
//--------录音 beware of if...if...if...if...expressions
59+
system("amixer set Capture 53");
60+
system("amixer set 'ADC PCM' 240");
61+
62+
if (!device_open(SND_PCM_STREAM_CAPTURE ))return 1;
63+
//printf("---device_open()\n");
64+
if (!device_setparams(1,8000)) return 2;
65+
//printf("---device_setparams()\n");
66+
if(!device_check_voice()) //--checking voice wave amplitude, and start to record if it exceeds preset threshold value,or it will loop checking ...
67+
continue;
68+
69+
printf("start recording...\n");
70+
if (!device_capture( 10 ))return 3;
71+
//printf("-----device_capture()\n");
72+
snd_pcm_close( pcm_handle );
73+
printf("record finish!\n");
74+
75+
fd=open("/tmp/record.raw",O_WRONLY|O_CREAT|O_TRUNC);
76+
rc=write(fd,wave_buf,wave_buf_len);
77+
printf("write to record.raw %d bytes\n",rc);
78+
close(fd); //though kernel will close it automatically
79+
80+
//--------播放
81+
printf("start playback...\n");
82+
if (!device_open(SND_PCM_STREAM_PLAYBACK)) return 4;
83+
//printf("-----PLAY: device_open() finish\n");
84+
if (!device_setparams(1,8000)) return 5;
85+
//printf("-----PLAY: device_setarams() finish\n");
86+
if (!device_play()) return 6;
87+
printf("finish playback.\n\n\n");
88+
89+
snd_pcm_close( pcm_handle );
90+
//printf("-----PLAY: snd_pcm_close() ----\n");
91+
92+
free(wave_buf); //--wave_buf mem. to be allocated in device_capture() and played in device_play();
93+
94+
}//while()
95+
96+
return 0;
97+
98+
}
99+
100+
101+
//首先让我们封装一个打开音频设备的函数:
102+
//snd_pcm_t *pcm_handle;
103+
104+
bool device_open(int mode){
105+
if(snd_pcm_open (&pcm_handle,"default",mode,0) < 0)
106+
{
107+
printf("snd_pcm_open() fail!\n");
108+
return false;
109+
}
110+
printf("snd_pcm_open() succeed!\n");
111+
return true;
112+
}
113+
114+
115+
bool device_setparams(int nchanl,int rate)
116+
{
117+
unsigned int val;
118+
int dir;
119+
int rc;
120+
snd_pcm_hw_params_t *hw_params;
121+
122+
//------ beware of following if..if...if..if...if...expressions ----------
123+
if(snd_pcm_hw_params_malloc (&hw_params) < 0)return false; //为参数变量分配空间
124+
// printf("---- snd_pcm_hw_params_malloc(&hw_params) ----\n");
125+
if(snd_pcm_hw_params_malloc (&params) < 0)return false;
126+
// printf("----snd_pcm_hw_params_malloc(&params) ----\n");
127+
if(snd_pcm_hw_params_any (pcm_handle, hw_params) < 0)return false; //参数初始化
128+
// printf("----snd_pcm_hw_params_any(pcm_handle,hw_params)----\n");
129+
if(snd_pcm_hw_params_set_access (pcm_handle, hw_params,SND_PCM_ACCESS_RW_INTERLEAVED) < 0)return false; //设置为交错模式
130+
// printf("----snd_pcm_hw_params_set_access()----\n");
131+
if(snd_pcm_hw_params_set_format( pcm_handle, hw_params, SND_PCM_FORMAT_S16_LE) < 0)return false; //使用用16位样本
132+
// printf("----snd_pmc_hw_params_set_format()-----\n");
133+
val=rate;//8000;
134+
if(snd_pcm_hw_params_set_rate_near( pcm_handle, hw_params,&val,0) < 0)return false; //设置采样率
135+
// printf("----snd_pcm_hw_params_set_rate_near() val=%d----\n",val);
136+
if(snd_pcm_hw_params_set_channels( pcm_handle, hw_params, nchanl) < 0)return false; //设置为立体声or Mono.
137+
// printf("----snd_pcm_hw_params_set_channels()-----\n");
138+
frames=32;
139+
if(snd_pcm_hw_params_set_period_size_near(pcm_handle,hw_params,&chunk_size,&dir) < 0 )return false;
140+
// printf("----snd_pcm_hw_params_set_period_size_near() chunk_size=%d----\n",chunk_size);
141+
if(snd_pcm_hw_params_get_period_size( hw_params, &period_size,0) < 0)return false; //获取周期长度
142+
// printf("----snd_pcm_hw_get_period_size(): %d----\n",(int)period_size);
143+
if(snd_pcm_hw_params_get_format(hw_params,&format_val) < 0)return false;
144+
// printf("----snd_pcm_hw_params_get_format()----\n");
145+
bit_per_sample = snd_pcm_format_width((snd_pcm_format_t)format_val);
146+
//printf("---bit_per_sample=%d snd_pcm_format_width()----\n",bit_per_sample);
147+
//获取样本长度
148+
snd_pcm_hw_params_get_channels(hw_params,&chanl_val);
149+
//printf("----snd_pcm_hw_params_get_channels %d---\n",chanl_val);
150+
chunk_byte = period_size*bit_per_sample*chanl_val/8;
151+
//chunk_size = frames;//period_size; //frames
152+
//计算周期长度(字节数(bytes) = 每周期的桢数 * 样本长度(bit) * 通道数 / 8 )
153+
154+
rc=snd_pcm_hw_params( pcm_handle, hw_params); //设置参数
155+
if(rc<0){
156+
printf("unable to set hw parameters:%s\n",snd_strerror(rc));
157+
exit(1);
158+
}
159+
printf("finish setting sound hw parameters\n");
160+
params = hw_params; //保存参数,方便以后使用
161+
snd_pcm_hw_params_free( hw_params); //释放参数变量空间
162+
//printf("----snd_pcm_hw_params_free()----\n");
163+
return true;
164+
165+
}
166+
//这里先使用了Alsa提供的一系列snd_pcm_hw_params_set_函数为参数变量赋值。
167+
//最后才通过snd_pcm_hw_params将参数传递给设备。
168+
//需要说明的是正式的开发中需要处理参数设置失败的情况,这里仅做为示例程序而未作考虑。
169+
//设置好参数后便可以开始录音了。录音过程实际上就是从音频设备中读取数据信息并保存。
170+
171+
172+
173+
bool device_capture( int dtime ){
174+
snd_pcm_hw_params_get_rate(params,&rate_val,&dir); //params=hw_params
175+
wave_buf_len=dtime*rate_val*bit_per_sample*chanl_val/8;
176+
//printf(" wave_buf_len=%d \n",wave_buf_len);
177+
//计算音频数据长度(秒数 * 采样率 * 桢长度)
178+
char *data=wave_buf=(char*)malloc(wave_buf_len);
179+
int r = 0;
180+
chunk_size=32;
181+
chunk_byte=chunk_size*bit_per_sample*chanl_val/8;
182+
//printf("chunk_byte=%d\n",chunk_byte);
183+
while ( (data-wave_buf) <= (wave_buf_len-chunk_byte) ){ //chunk_size*bit_per_sample*chanl_val)){
184+
r = snd_pcm_readi( pcm_handle,data,chunk_size); //chunk_size*bit_per_sample*read interleaved rames from a PCM
185+
//--- snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm,void* buffer, snd_pcm_uframes_t size)
186+
//--- pcm -PCM handle buffer-frames containing buffer size - frames to be read
187+
if ( r>0 ) {
188+
// printf(" r= %d\n",r);
189+
// printf("data=%d wave_buf=%d\n",data,wave_buf);
190+
data += chunk_byte;//--move current buffer position pointer
191+
}
192+
else
193+
return false;
194+
}
195+
196+
return true;
197+
198+
}
199+
200+
//形参dtime用来确定录音时间,根据录音时间分配数据空间,再调用snd_pcm_readi从音频设备读取音频数据,存放到wave_buf中。
201+
//同样的原理,我们再添加一个播放函数,向音频设备写入数据:
202+
203+
bool device_play(){
204+
char *data = wave_buf;
205+
int r = 0;
206+
chunk_size=32;
207+
chunk_byte=chunk_size*bit_per_sample*chanl_val/8;
208+
while ( (data-wave_buf) <= (wave_buf_len-chunk_byte)){
209+
r = snd_pcm_writei( pcm_handle, data , chunk_size); //chunk_size = frames
210+
if(r == -EAGAIN)continue;
211+
if(r < 0){
212+
printf("wirte error: %s\n",snd_strerror(r));
213+
exit(EXIT_FAILURE);
214+
}
215+
//printf("----- writei() r=%d -----\n ",r);
216+
if ( r>0 ) data += chunk_byte;
217+
else
218+
return false;
219+
}
220+
return true;
221+
222+
}
223+
224+
225+
bool device_check_voice(void )
226+
{
227+
int i;
228+
int r = 0;
229+
int count=0;
230+
int total=0;
231+
int averg=0;//average of sample values in one chunk.
232+
chunk_size=32; //--frames each time
233+
chunk_byte=chunk_size*bit_per_sample*chanl_val/8; //---bytes
234+
//printf("chunk_byte=%d\n",chunk_byte);
235+
int16_t *buf=(int16_t *)malloc(chunk_byte); //32bits
236+
//printf("size of int16_t = %d\n",sizeof(int16_t));
237+
int16_t *data=buf;
238+
//char* tmp;
239+
240+
printf("listening and checking any voice......\n");
241+
while(1)
242+
{
243+
r = snd_pcm_readi( pcm_handle,(char *)buf,chunk_size); //chunk_size*bit_per_sample*read interleaved rames from a PCM
244+
if(r == -EAGAIN)continue;
245+
if ( r>=0 ) {
246+
//printf(" r= %d \n ",r);
247+
data=buf;
248+
averg=0;total=0;
249+
for(i=0;i<r;i++){
250+
total+=abs((*data)); // !!!!!!
251+
data+=1;
252+
}
253+
//printf("total=%d\n",total);
254+
averg=(total>>5);
255+
//printf("averg=%d\n",averg);
256+
if(averg >= CHECK_AVERG){
257+
printf("loud noise sensed!\n");
258+
free(buf);
259+
return true;
260+
}
261+
262+
// usleep(20000); //
263+
// snd_pcm_prepare(pcm_handle);
264+
//usleep(10000); //---you cann't sleep here,
265+
}//if
266+
else
267+
{
268+
printf(" r= %d \n ",r);
269+
free(buf);
270+
return false;
271+
}
272+
} //while(1)
273+
274+
free(buf);
275+
return true;
276+
277+
}

0 commit comments

Comments
 (0)