diff options
author | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2013-02-18 23:48:36 +0200 |
---|---|---|
committer | Gluzskiy Alexandr <sss@sss.chaoslab.ru> | 2013-02-18 23:48:36 +0200 |
commit | 908fc2b63dca73ba642bacaf8bb7a038b8df3880 (patch) | |
tree | 2b93e1030cb26325cdda2d732688e4ab3136d75c | |
parent | 3ab3d03b8b603f210d878d352b56442eec14f6af (diff) |
sound detector (like "motion")
-rw-r--r-- | sound_detector/main.cpp | 235 | ||||
-rw-r--r-- | sound_detector/sound_detector.project | 105 |
2 files changed, 340 insertions, 0 deletions
diff --git a/sound_detector/main.cpp b/sound_detector/main.cpp new file mode 100644 index 0000000..068964c --- /dev/null +++ b/sound_detector/main.cpp @@ -0,0 +1,235 @@ + +#ifndef WIN32 +#include <unistd.h> +#endif +#include <cstdint> + +//c +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +//c++ +#include <vector> +#include <fstream> + +//portaudio +#include <portaudio.h> + +//ffmpeg + +#include <libavcodec/avcodec.h> +#include <libavformat/avformat.h> +#include <libswresample/swresample.h> + +//boost +#include <boost/thread.hpp> +#include <boost/bind.hpp> + +//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<int16_t> 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<char*>(&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]; + fwrite(&buffer[i], sizeof(int16_t), 1, file); +/* const char *test = reinterpret_cast<char*>(&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 <dev number> -o <path>\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 <dev number> -o <path>\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; +} diff --git a/sound_detector/sound_detector.project b/sound_detector/sound_detector.project new file mode 100644 index 0000000..b14f4ac --- /dev/null +++ b/sound_detector/sound_detector.project @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="utf-8"?> +<CodeLite_Project Name="sound_detector" InternalType="Console"> + <Plugins> + <Plugin Name="qmake"> + <![CDATA[00010001N0005Debug000000000000]]> + </Plugin> + </Plugins> + <Description/> + <Dependencies/> + <VirtualDirectory Name="src"> + <File Name="main.cpp"/> + </VirtualDirectory> + <Settings Type="Executable"> + <GlobalSettings> + <Compiler Options="" C_Options=""> + <IncludePath Value="."/> + </Compiler> + <Linker Options=""> + <LibraryPath Value="."/> + </Linker> + <ResourceCompiler Options=""/> + </GlobalSettings> + <Configuration Name="Debug" CompilerType="gnu g++" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append"> + <Compiler Options="-g;-Wall;-O0;-std=gnu++0x" C_Options="-g;-Wall;-O0;-std=gnu99" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags=""> + <IncludePath Value="."/> + </Compiler> + <Linker Options="" Required="yes"> + <Library Value="portaudio"/> + <Library Value="avcodec"/> + <Library Value="avformat"/> + <Library Value="swresample"/> + <Library Value="boost_thread"/> + <Library Value="boost_system"/> + </Linker> + <ResourceCompiler Options="" Required="no"/> + <General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Debug" Command="./$(ProjectName)" CommandArguments="-d4 -o." UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/> + <Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>"> + <![CDATA[]]> + </Environment> + <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath=""> + <PostConnectCommands/> + <StartupCommands/> + </Debugger> + <PreBuild/> + <PostBuild/> + <CustomBuild Enabled="no"> + <RebuildCommand/> + <CleanCommand/> + <BuildCommand/> + <PreprocessFileCommand/> + <SingleFileCommand/> + <MakefileGenerationCommand/> + <ThirdPartyToolName>None</ThirdPartyToolName> + <WorkingDirectory/> + </CustomBuild> + <AdditionalRules> + <CustomPostBuild/> + <CustomPreBuild/> + </AdditionalRules> + <Completion EnableCpp11="no"> + <ClangCmpFlagsC/> + <ClangCmpFlags/> + <ClangPP/> + <SearchPaths/> + </Completion> + </Configuration> + <Configuration Name="Release" CompilerType="gnu g++" DebuggerType="GNU gdb debugger" Type="" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append"> + <Compiler Options="-O2;-Wall" C_Options="-O2;-Wall" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags=""> + <IncludePath Value="."/> + </Compiler> + <Linker Options="" Required="yes"/> + <ResourceCompiler Options="" Required="no"/> + <General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Release" Command="./$(ProjectName)" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/> + <Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>"> + <![CDATA[]]> + </Environment> + <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath=""> + <PostConnectCommands/> + <StartupCommands/> + </Debugger> + <PreBuild/> + <PostBuild/> + <CustomBuild Enabled="no"> + <RebuildCommand/> + <CleanCommand/> + <BuildCommand/> + <PreprocessFileCommand/> + <SingleFileCommand/> + <MakefileGenerationCommand/> + <ThirdPartyToolName>None</ThirdPartyToolName> + <WorkingDirectory/> + </CustomBuild> + <AdditionalRules> + <CustomPostBuild/> + <CustomPreBuild/> + </AdditionalRules> + <Completion EnableCpp11="no"> + <ClangCmpFlagsC/> + <ClangCmpFlags/> + <ClangPP/> + <SearchPaths/> + </Completion> + </Configuration> + </Settings> +</CodeLite_Project> |