2 #include <alsa/asoundlib.h> 24 #define SAMPLE_RATE 16000 26 #define SAMPLE_BIT_SIZE 16 32 #define DEF_BUFF_TIME 500000 34 #define DEF_PERIOD_TIME 100000 39 bool is_speech =
false;
60 for (
int i = 0; i < pcm_data.
size; i++)
62 energy += pcm_data.
data[i] * pcm_data.
data[i];
64 energy = 10 * log(energy);
74 if (tmp == SND_PCM_FORMAT_UNKNOWN)
85 error_code = snd_pcm_open((snd_pcm_t**)&record_->wavein_hdl, dev.
u.
name, SND_PCM_STREAM_CAPTURE, 0);
88 std::cout <<
"unable to open pcm device: " << snd_strerror(error_code) << std::endl;
92 snd_pcm_hw_params_alloca(¶ms_);
93 handle_ = (snd_pcm_t*)record_->wavein_hdl;
95 error_code = snd_pcm_hw_params_any(handle_, params_);
98 std::cout <<
"Broken configuration for this PCM: " << snd_strerror(error_code) << std::endl;
104 error_code = snd_pcm_hw_params_set_access(handle_, params_, SND_PCM_ACCESS_RW_INTERLEAVED);
107 std::cout <<
"Access type not available: " << snd_strerror(error_code) << std::endl;
115 std::cout <<
"Invalid format";
118 error_code = snd_pcm_hw_params_set_format(handle_, params_, format_);
121 std::cout <<
"Sample format not available: " << snd_strerror(error_code) << std::endl;
126 error_code = snd_pcm_hw_params_set_channels(handle_, params_, wavfmt->
nChannels);
129 std::cout <<
"Channels count not available: " << snd_strerror(error_code) << std::endl;
135 error_code = snd_pcm_hw_params_set_rate_near(handle_, params_, &record_rate_, 0);
138 std::cout <<
"Set rate failed: " << snd_strerror(error_code) << std::endl;
144 error_code = snd_pcm_hw_params_set_period_size_near(handle_, params_, &frames_, 0);
147 std::cout <<
"set period time fail: " << snd_strerror(error_code) << std::endl;
152 error_code = snd_pcm_hw_params(handle_, params_);
155 std::cout <<
"Unable to install hw params: " << snd_strerror(error_code) << std::endl;
159 error_code = snd_pcm_hw_params_get_period_size(params_, &frames_, 0);
162 std::cout <<
"\n get_period_size failed !!!\n" << snd_strerror(error_code) << std::endl;
166 record_->audiobuf = (
char*)malloc(audiobuf_size_);
167 if (record_->audiobuf == NULL)
169 std::cout <<
"\n Malloc failed in rec->audiobuf !!!\n";
173 error_code = snd_pcm_hw_params_get_period_time(params_, &record_rate_, 0);
176 std::cout <<
"\n get_period_time failed !!!\n" << snd_strerror(error_code) << std::endl;
183 duration_time_ = (int)(duration_time * pow(10, 6));
184 record_loop_ = duration_time_ / record_rate_;
191 audio_pcm_ = { NULL, 0 };
192 error_code = snd_pcm_readi(handle_, record_->audiobuf, frames_);
193 if (error_code == -EPIPE)
196 std::cout <<
"overrun occurred\n";
197 snd_pcm_prepare(handle_);
200 else if (error_code < 0)
202 std::cout <<
"error from read: " << snd_strerror(error_code) << std::endl;
205 else if (error_code != (
int)frames_)
207 std::cout <<
"short read, read " << error_code <<
" frames\n";
210 audio_pcm_.data = record_->audiobuf;
211 audio_pcm_.size = audiobuf_size_;
217 snd_pcm_drop(handle_);
218 snd_pcm_drain(handle_);
219 snd_pcm_close(handle_);
227 return snd_pcm_start(pcm);
232 return snd_pcm_drop(pcm);
237 snd_pcm_state_t state;
238 state = snd_pcm_state((snd_pcm_t*)rec->
wavein_hdl);
241 case SND_PCM_STATE_RUNNING:
242 case SND_PCM_STATE_DRAINING:
252 unsigned int periodtime)
254 snd_pcm_hw_params_t* params;
257 snd_pcm_format_t format;
258 snd_pcm_uframes_t size;
259 snd_pcm_t* handle = (snd_pcm_t*)rec->
wavein_hdl;
262 snd_pcm_hw_params_alloca(¶ms);
263 err = snd_pcm_hw_params_any(handle, params);
266 dbg(
"Broken configuration for this PCM");
270 err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
274 dbg(
"Access type not available");
282 dbg(
"Invalid format");
286 err = snd_pcm_hw_params_set_format(handle, params, format);
290 dbg(
"Sample format non available");
294 err = snd_pcm_hw_params_set_channels(handle, params, wavfmt->
nChannels);
298 dbg(
"Channels count non available");
304 err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
308 dbg(
"Set rate failed");
314 dbg(
"Rate mismatch");
320 err = snd_pcm_hw_params_get_buffer_time_max(params, &rec->
buffer_time, 0);
328 err = snd_pcm_hw_params_set_period_time_near(handle, params, &rec->
period_time, 0);
331 dbg(
"set period time fail");
335 err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &rec->
buffer_time, 0);
338 dbg(
"set buffer time failed");
342 err = snd_pcm_hw_params_get_period_size(params, &size, 0);
345 dbg(
"get period size fail");
351 err = snd_pcm_hw_params_get_buffer_size(params, &size);
354 dbg(
"Can't use period equal to buffer size (%lu == %lu)", size, rec->
period_frames);
362 err = snd_pcm_hw_params(handle, params);
365 dbg(
"Unable to install hw params:");
374 snd_pcm_sw_params_t* swparams;
375 snd_pcm_t* handle = (snd_pcm_t*)(rec->
wavein_hdl);
378 snd_pcm_sw_params_alloca(&swparams);
379 err = snd_pcm_sw_params_current(handle, swparams);
382 dbg(
"get current sw para fail");
386 err = snd_pcm_sw_params_set_avail_min(handle, swparams, rec->
period_frames);
389 dbg(
"set avail min failed");
396 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, rec->
buffer_frames * 2);
400 dbg(
"set start threshold fail");
404 if ((err = snd_pcm_sw_params(handle, swparams)) < 0)
406 dbg(
"unable to install sw params:");
447 dbg(
"!!!!!!overrun happend!!!!!!");
448 err = snd_pcm_prepare(handle);
452 dbg(
"Can't recovery from overrun," 453 "prepare failed: %s\n",
459 else if (err == -ESTRPIPE)
461 while ((err = snd_pcm_resume(handle)) == -EAGAIN)
465 err = snd_pcm_prepare(handle);
469 dbg(
"Can't recovery from suspend," 470 "prepare failed: %s\n",
483 size_t count = rcount;
486 snd_pcm_t* handle = (snd_pcm_t*)rec->
wavein_hdl;
495 r = snd_pcm_readi(handle, data, count);
496 if (r == -EAGAIN || (r >= 0 && (
size_t)r < count))
498 snd_pcm_wait(handle, 100);
520 size_t frames, bytes;
521 sigset_t mask, oldmask;
524 sigaddset(&mask, SIGINT);
525 sigaddset(&mask, SIGTERM);
526 pthread_sigmask(SIG_BLOCK, &mask, &oldmask);
536 std::cout <<
"RECORD_STATE_CLOSING and break!!!\n";
541 std::cout <<
"rec->state < RECORD_STATE_RECORDING and usleep!!!\n";
544 if (
pcm_read(rec, frames) != frames)
592 err = snd_pcm_open((snd_pcm_t**)&rec->
wavein_hdl, dev.
u.
name, SND_PCM_STREAM_CAPTURE, 0);
632 snd_pcm_close(handle);
646 char *io, *filter, *name;
649 if (snd_device_name_hint(-1,
"pcm", &hints) < 0)
653 filter = stream == SND_PCM_STREAM_CAPTURE ? (
char*)
"Input" : (
char*)
"Output";
656 io = snd_device_name_get_hint(*n,
"IOID");
657 name = snd_device_name_get_hint(*n,
"NAME");
658 if (name && (io == NULL || strcmp(io, filter) == 0))
668 snd_device_name_free_hint(hints);
683 id.
u.
name = (
char*)
"default";
708 memset(myrec, 0,
sizeof(
struct recorder));
726 std::cout <<
"rec->state is : " << rec->
state << std::endl;
static ssize_t pcm_read(struct recorder *rec, size_t rcount)
static int getPcmDeviceCount(snd_pcm_stream_t stream)
int isRecordStopped(struct recorder *rec)
static int stopRecordInternal(snd_pcm_t *pcm)
static int openRecorderInternal(struct recorder *rec, record_dev_id dev, WAVEFORMATEX *fmt, std::string base_path)
static int format_ms_to_alsa(const WAVEFORMATEX *wavfmt, snd_pcm_format_t *format)
static int set_swparams(struct recorder *rec)
static void * recordThreadProc(void *para)
float energyPerSample(struct DataBuff pcm_data)
static int isStoppedInternal(struct recorder *rec)
int createRecorder(struct recorder **out_rec, void(*on_data_ind)(char *data, unsigned long len, void *user_cb_para), void *user_cb_para)
int setRecordDuration(const float duration_time)
static void free_rec_buffer(struct recorder *rec)
static int startRecordInternal(snd_pcm_t *pcm)
record_dev_id * listInputDevice()
static int set_params(struct recorder *rec, WAVEFORMATEX *fmt, unsigned int buffertime, unsigned int periodtime)
void initRecord(struct recorder *rec, record_dev_id dev, WAVEFORMATEX *fmt)
float levelEnergy(struct DataBuff pcm_data, const int call_count)
static void closeRecorderInternal(struct recorder *rec)
int openRecorder(struct recorder *rec, record_dev_id dev, WAVEFORMATEX *fmt, std::string base_path)
union record_dev_id::@9 u
const std::string base_path
void closeRecorder(struct recorder *rec)
int startRecord(struct recorder *rec)
void destroyRecorder(struct recorder *rec)
static int createRecordThread(void *para, pthread_t *tidp, std::string base_path)
int stopRecord(struct recorder *rec)
static int set_hwparams(struct recorder *rec, const WAVEFORMATEX *wavfmt, unsigned int buffertime, unsigned int periodtime)
void(* on_data_ind)(char *data, unsigned long len, void *user_para)
static int prepareRecBuffer(struct recorder *rec)
record_dev_id getDefaultInputDevice()
std::string pcm_file_path
static int xrun_recovery(snd_pcm_t *handle, int err)