#include "sound.hpp" #include "bfsk.hpp" #include "config.hpp" #include "x25519_handshake.hpp" #include #include #include #include #include #include constexpr int CAPTURE_SECONDS=3; static std::atomic gSoundActive{false}; static std::thread gSoundThread; static std::vector gInputBuffer; static size_t gWritePos=0; static std::vector gOutputBuffer; static size_t gReadPos=0; static int audioCallback(const void *input,void *output,unsigned long frameCount,const PaStreamCallbackTimeInfo*,PaStreamCallbackFlags,void*){ const float *in=(const float*)input; float *out=(float*)output; for(unsigned long i=0;idefaultLowInputLatency; inParams.hostApiSpecificStreamInfo=nullptr; outParams.device=Pa_GetDefaultOutputDevice(); if(outParams.device==paNoDevice){Pa_Terminate();return;} outParams.channelCount=2; outParams.sampleFormat=paFloat32; outParams.suggestedLatency=Pa_GetDeviceInfo(outParams.device)->defaultLowOutputLatency; outParams.hostApiSpecificStreamInfo=nullptr; PaStream* stream=nullptr; err=Pa_OpenStream(&stream,&inParams,&outParams,SAMPLE_RATE,256,paNoFlag,audioCallback,nullptr); if(err!=paNoError){Pa_Terminate();return;} err=Pa_StartStream(stream); if(err!=paNoError){Pa_CloseStream(stream);Pa_Terminate();return;} Pa_Sleep(CAPTURE_SECONDS*1000); Pa_StopStream(stream); Pa_CloseStream(stream); Pa_Terminate(); auto received=bfskDemodulate(gInputBuffer); if(!received.empty()){ if(received.size()>=33 && received[0]=='E'){ uint8_t otherPub[32]; for(int i=0;i<32;i++){ otherPub[i]=received[1+i]; } x25519ComputeShared(config,otherPub); } } gSoundActive=false; } void soundFind(AppConfig &config){ if(config.soundExchangeActive)return; config.soundExchangeActive=true; gSoundActive=true; x25519GenerateEphemeral(config); std::vector packet;packet.push_back('E'); packet.insert(packet.end(),config.ephemeralPub,config.ephemeralPub+32); gOutputBuffer=bfskModulate(packet); gReadPos=0; gInputBuffer.clear(); gInputBuffer.resize(SAMPLE_RATE*CAPTURE_SECONDS,0.0f); gWritePos=0; gSoundThread=std::thread(soundThreadFunc,config); } void soundLose(AppConfig &config){ if(!config.soundExchangeActive)return; config.soundExchangeActive=false; if(gSoundActive)gSoundActive=false; if(gSoundThread.joinable())gSoundThread.join(); }