#ifndef WIN32 #include #endif #include //c #include #include #include //c++ #include #include //portaudio #include //ffmpeg #include #include #include //boost #include #include //FILE *file = NULL; //int max_len = 1024*1024*32, len = 0; const unsigned int pecapture = 3, postcapture = 7, min_length = 1, thresold_percent = 5; unsigned rate = 0, current_file = 0; bool sound_detected = false; //std::ofstream file; FILE *file = NULL; boost::mutex lock; std::vector buffer; void handle_data() { while(true) { boost::this_thread::sleep(boost::posix_time::seconds(1)); printf("buffer contain %u, required %d\n", buffer.size(), rate*3); if(!sound_detected) { if(buffer.size() > rate * 3) { int thresold = (int)((float)INT16_MAX/100.0*(float)thresold_percent), noise = 0; lock.lock(); for(size_t i = 0; i < buffer.size(); i++) { if(buffer[i] > thresold) noise++; } printf("noise detected %d, noise required %d\n", noise, ((min_length * rate) / 10)); if(noise > ((min_length * rate) /10)) //need to do some research { printf("write started\n"); char filename[128]; snprintf(filename, 127, "./file%d.pcm", current_file); //file.open(filename); file = fopen(filename, "wb"); ++current_file; for(size_t i = 0; i < buffer.size(); i++) { fwrite(&buffer[i], sizeof(int16_t), 1, file); /* const char *test = reinterpret_cast(&buffer[i]); file.write(test, sizeof(test)); */ // file.put((char)buffer[i]<<8); // file.put((char)buffer[i]); } sound_detected = true; } buffer.clear(); lock.unlock(); } } else { if(buffer.size() > (rate * ((postcapture > 3)?postcapture:3))) { int thresold = (int)((float)INT16_MAX/100.0*(float)thresold_percent), silence = 0; lock.lock(); for(size_t i = 0; i < buffer.size(); i++) { //file.put(buffer[i]); //file<(&buffer[i]); file.write(test, sizeof(test)); */ // file.put((char)buffer[i]<<8); // file.put((char)buffer[i]); if(buffer[i] < thresold) silence++; else silence = 0; } printf("silence detected %d, silence required %d\n", silence, (postcapture * rate)); buffer.clear(); lock.unlock(); if(silence > (rate * postcapture)) { printf("write stopped\n"); //file.close(); fclose(file); sound_detected = false; } } } } } int stream_callback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { int16_t *buf = (int16_t*)input; lock.lock(); buffer.insert(buffer.end(), buf, buf + frameCount); lock.unlock(); //debug /* for(unsigned long i = 0; i < frameCount; i++) { if(buf[i] > (int)((float)INT16_MAX/100.0*(float)thresold_percent)) printf("%d ", buf[i]); } */ return paContinue; //debug end } double get_lowest_rate(const PaStreamParameters *inputParameters) { static double standardSampleRates[] = { 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */ }; for(int i=0; standardSampleRates[i] > 0; i++) { if(Pa_IsFormatSupported(inputParameters, NULL, standardSampleRates[i]) == paFormatIsSupported) { rate = standardSampleRates[i]; return rate; } } return 0; } int main(int argc, char **argv) { PaError err = Pa_Initialize(); if(err != paNoError) { printf("PortAudio error: %s\n", Pa_GetErrorText(err)); return 1; } int opt = -1, device = -1; char out_dir[1024] = {0}; if(argc == 1) { printf("usage:\n%s -h -l -d -o \n\t-h\tthis help message\n\t-l\tdevice list\n\t-d\tdevice number from device list\n\t-o\toutput directory\n", argv[0]); return 0; } while((opt = getopt(argc, argv, "hld:o:")) != -1) { switch(opt) { break; case 'l': for(PaDeviceIndex i =0, end = Pa_GetDeviceCount(); i < end; i++) { const PaDeviceInfo *info = Pa_GetDeviceInfo(i); printf("%d. %s, input channels %d, output channels %d, default sample rate %f, lowest input latency %f, highest input latency %f\n", i, info->name, info->maxInputChannels, info->maxOutputChannels, info->defaultSampleRate, info->defaultLowInputLatency, info->defaultHighInputLatency); } break; case 'o': strcpy(out_dir, optarg); break; case 'd': device = atoi(optarg); break; case 'h': default: printf("usage:\n%s -h -l -d -o \n\t-h\tthis help message\n\t-l\tdevice list\n\t-d\tdevice number from device list\n\t-o\toutput directory\n", argv[0]); break; }; } if(device == -1) { printf("ERROR: device number is required\n"); return 1; } if(!out_dir[0]) { printf("ERROR: output directory is required\n"); return 1; } PaStream *stream; PaStreamParameters params; memset(¶ms, 0, sizeof(PaStreamParameters)); params.channelCount = 1; params.sampleFormat = paInt16; params.device = device; const PaDeviceInfo *info = Pa_GetDeviceInfo(device); params.suggestedLatency = info->defaultHighInputLatency; err = Pa_OpenStream(&stream, ¶ms, NULL, get_lowest_rate(¶ms), paFramesPerBufferUnspecified, paNoFlag, stream_callback, NULL); if(err != paNoError) printf("PortAudio error: %s\n", Pa_GetErrorText(err)); //debug //file = fopen("./data_dump", "wb"); //end debug new boost::thread(boost::bind(handle_data)); Pa_StartStream(stream); while(true) sleep(1); err = Pa_Terminate(); if(err != paNoError) { printf("PortAudio error: %s\n", Pa_GetErrorText(err)); return 1; } return 0; }