diff --git a/NoiseGate/NoiseGate.cpp b/NoiseGate/NoiseGate.cpp index 597a7e1d..c7586a4f 100644 --- a/NoiseGate/NoiseGate.cpp +++ b/NoiseGate/NoiseGate.cpp @@ -74,8 +74,7 @@ void NoiseGateFilter::ApplyNoiseGate(float *buffer, int totalFloats) if(totalFloats % 2) return; // Odd number of samples - // OBS is currently hard-coded to 48ksps - const float SAMPLE_RATE_F = 48000.0f; + const float SAMPLE_RATE_F = float(OBSGetSampleRateHz()); const float dtPerSample = 1.0f / SAMPLE_RATE_F; // Convert configuration times into per-sample amounts @@ -83,10 +82,9 @@ void NoiseGateFilter::ApplyNoiseGate(float *buffer, int totalFloats) const float releaseRate = 1.0f / (parent->releaseTime * SAMPLE_RATE_F); // Determine level decay rate. We don't want human voice (75-300Hz) to cross the close - // threshold if the previous peak crosses the open threshold. 75Hz at 48ksps is 640 - // samples between peaks. + // threshold if the previous peak crosses the open threshold. const float thresholdDiff = parent->openThreshold - parent->closeThreshold; - const float minDecayPeriod = (1.0f / 75.0f) * SAMPLE_RATE_F; // 640 samples + const float minDecayPeriod = (1.0f / 75.0f) * SAMPLE_RATE_F; const float decayRate = thresholdDiff / minDecayPeriod; // We can't use SSE as the processing of each sample depends on the processed diff --git a/OBS.rc b/OBS.rc index 86703121..a3b7ed56 100644 --- a/OBS.rc +++ b/OBS.rc @@ -126,7 +126,7 @@ BEGIN RTEXT "Settings.Encoding.Audio.Bitrate",IDC_STATIC,221,85,128,8 COMBOBOX IDC_AUDIOBITRATE,354,83,61,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP RTEXT "Settings.Encoding.Audio.Format",IDC_STATIC,10,101,138,8 - COMBOBOX IDC_AUDIOFORMAT,152,99,264,62,CBS_DROPDOWNLIST | WS_DISABLED | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_AUDIOFORMAT,152,99,264,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Settings.Info",IDC_INFO,4,122,417,37,NOT WS_VISIBLE END diff --git a/OBSApi/APIDefs.cpp b/OBSApi/APIDefs.cpp index 09bb28eb..2e67f934 100644 --- a/OBSApi/APIDefs.cpp +++ b/OBSApi/APIDefs.cpp @@ -141,4 +141,6 @@ void OBSGetCurMicVolumeStats(float *rms, float *max, float *peak) {API->Ge void OBSAddSettingsPane(SettingsPane *pane) {API->AddSettingsPane(pane);} void OBSRemoveSettingsPane(SettingsPane *pane) {API->RemoveSettingsPane(pane);} -UINT OBSGetAPIVersion() {return 0x0100;} +UINT OBSGetAPIVersion() {return 0x0101;} + +UINT OBSGetSampleRateHz() {return API->GetSampleRateHz();} diff --git a/OBSApi/APIInterface.h b/OBSApi/APIInterface.h index af842495..71c476df 100644 --- a/OBSApi/APIInterface.h +++ b/OBSApi/APIInterface.h @@ -172,6 +172,8 @@ public: virtual Vect2 MapFrameToWindowSize(Vect2 frameSize) const=0; virtual Vect2 GetWindowToFrameScale() const=0; virtual Vect2 GetFrameToWindowScale() const=0; + + virtual UINT GetSampleRateHz() const=0; }; BASE_EXPORT extern APIInterface *API; @@ -286,3 +288,5 @@ BASE_EXPORT void OBSRemoveSettingsPane(SettingsPane *pane); /** gets API version. version is formatted: 0xMMmm */ BASE_EXPORT UINT OBSGetAPIVersion(); + +BASE_EXPORT UINT OBSGetSampleRateHz(); diff --git a/OBSApi/AudioSource.cpp b/OBSApi/AudioSource.cpp index de250785..f359e35c 100644 --- a/OBSApi/AudioSource.cpp +++ b/OBSApi/AudioSource.cpp @@ -87,7 +87,9 @@ void AudioSource::InitAudioData(bool bFloat, UINT channels, UINT samplesPerSec, //----------------------------- - if(inputSamplesPerSec != 48000) + UINT sampleRateHz = OBSGetSampleRateHz(); + + if(inputSamplesPerSec != sampleRateHz) { int errVal; @@ -96,12 +98,11 @@ void AudioSource::InitAudioData(bool bFloat, UINT channels, UINT samplesPerSec, if(!resampler) CrashError(TEXT("AudioSource::InitAudioData: Could not initiate resampler")); - resampleRatio = 48000.0 / double(inputSamplesPerSec); + resampleRatio = double(sampleRateHz) / double(inputSamplesPerSec); bResample = true; //---------------------------------------------------- // hack to get rid of that weird first quirky resampled packet size - // (always returns a non-480 sized packet on the first resample) SRC_DATA data; data.src_ratio = resampleRatio; @@ -679,7 +680,7 @@ bool AudioSource::GetBuffer(float **buffer, QWORD targetTimestamp) } } - outputBuffer.SetSize(480*2); + outputBuffer.SetSize(OBSGetSampleRateHz()/100*2); *buffer = outputBuffer.Array(); diff --git a/Source/API.cpp b/Source/API.cpp index c4a29334..410c13ac 100644 --- a/Source/API.cpp +++ b/Source/API.cpp @@ -539,6 +539,8 @@ public: virtual void AddSettingsPane(SettingsPane *pane) {App->AddSettingsPane(pane);} virtual void RemoveSettingsPane(SettingsPane *pane) {App->RemoveSettingsPane(pane);} + + virtual UINT GetSampleRateHz() const {return App->GetSampleRateHz();} }; APIInterface* CreateOBSApiInterface() diff --git a/Source/Encoder_AAC.cpp b/Source/Encoder_AAC.cpp index 4852d6c2..966c3b55 100644 --- a/Source/Encoder_AAC.cpp +++ b/Source/Encoder_AAC.cpp @@ -46,7 +46,7 @@ public: { curBitRate = bitRate; - faac = faacEncOpen(48000, 2, &numReadSamples, &outputSize); + faac = faacEncOpen(App->GetSampleRateHz(), 2, &numReadSamples, &outputSize); //Log(TEXT("numReadSamples: %d"), numReadSamples); aacBuffer.SetSize(outputSize+2); @@ -155,7 +155,7 @@ public: inputBuffer.RemoveRange(0, numReadSamples); bufferedTimestamps << curEncodeTimestamp; - curEncodeTimestamp = curTimestamp + (((numReadSamples-lastSampleSize)/2)/48); + curEncodeTimestamp = curTimestamp + (((numReadSamples-lastSampleSize)/2)*1000/App->GetSampleRateHz()); } return ret > 0; diff --git a/Source/Encoder_MP3.cpp b/Source/Encoder_MP3.cpp index fef28c2e..bc8f29ff 100644 --- a/Source/Encoder_MP3.cpp +++ b/Source/Encoder_MP3.cpp @@ -59,8 +59,8 @@ public: if(!lgf) CrashError(TEXT("Unable to open mp3 encoder")); - lame_set_in_samplerate(lgf, 48000); - lame_set_out_samplerate(lgf, 48000); + lame_set_in_samplerate(lgf, App->GetSampleRateHz()); + lame_set_out_samplerate(lgf, App->GetSampleRateHz()); lame_set_num_channels(lgf, 2); lame_set_mode(lgf, STEREO); lame_set_disable_reservoir(lgf, TRUE); //bit reservoir has to be disabled for seamless streaming @@ -102,7 +102,7 @@ public: frameCounter -= outputFrameSize; bufferedTimestamps << curEncodeTimestamp; - curEncodeTimestamp = timestamp + ((outputFrameSize-lastSampleSize)/48); + curEncodeTimestamp = timestamp + ((outputFrameSize-lastSampleSize)*1000/App->GetSampleRateHz()); } int ret = lame_encode_buffer_interleaved_ieee_float(lgf, (float*)input, numInputFrames, MP3OutputBuffer.Array()+1, dwMP3MaxSize); diff --git a/Source/MP4FileStream.cpp b/Source/MP4FileStream.cpp index 0f21f99d..4f791f4e 100644 --- a/Source/MP4FileStream.cpp +++ b/Source/MP4FileStream.cpp @@ -57,7 +57,7 @@ struct MP4AudioFrameInfo inline UINT64 ConvertToAudioTime(DWORD timestamp, UINT64 minVal) { - UINT val = UINT64(timestamp)*48000/1000; + UINT val = UINT64(timestamp)*App->GetSampleRateHz()/1000; return MAX(val, minVal); } @@ -303,7 +303,7 @@ public: DWORD macTime = fastHtonl(DWORD(GetMacTime())); UINT videoDuration = fastHtonl(lastVideoTimestamp + App->GetFrameTime()); - UINT audioDuration = fastHtonl(lastVideoTimestamp + DWORD(double(audioFrameSize)/48)); + UINT audioDuration = fastHtonl(lastVideoTimestamp + DWORD(double(audioFrameSize)*1000.0/double(App->GetSampleRateHz()))); UINT width, height; App->GetOutputSize(width, height); @@ -453,7 +453,7 @@ public: output.OutputDword(0); //version and flags (none) output.OutputDword(macTime); //creation time output.OutputDword(macTime); //modified time - output.OutputDword(DWORD_BE(48000)); //time scale + output.OutputDword(DWORD_BE(App->GetSampleRateHz())); //time scale output.OutputDword(audioUnitDuration); output.OutputDword(bMP3 ? DWORD_BE(0x55c40000) : DWORD_BE(0x15c70000)); PopBox(output); //mdhd @@ -495,7 +495,7 @@ public: output.OutputWord(WORD_BE(16)); //sample size output.OutputWord(0); //quicktime audio compression id output.OutputWord(0); //quicktime audio packet size - output.OutputDword(DWORD_BE(48000<<16)); //sample rate (fixed point) + output.OutputDword(DWORD_BE(App->GetSampleRateHz()<<16)); //sample rate (fixed point) PushBox(output, DWORD_BE('esds')); output.OutputDword(0); //version and flags (none) output.OutputByte(3); //ES descriptor type diff --git a/Source/OBS.h b/Source/OBS.h index e156996a..60f4afcc 100644 --- a/Source/OBS.h +++ b/Source/OBS.h @@ -499,6 +499,8 @@ class OBS AudioSource *micAudio; List auxAudioSources; + UINT sampleRateHz; + AudioEncoder *audioEncoder; //--------------------------------------------------- @@ -913,6 +915,8 @@ public: OSLeaveMutex(hAuxAudioMutex); } + inline UINT GetSampleRateHz() const {return sampleRateHz;} + inline QWORD GetAudioTime() const {return latestAudioTime;} inline QWORD GetVideoTime() const {return latestVideoTime;} diff --git a/Source/OBSCapture.cpp b/Source/OBSCapture.cpp index 39213233..0df512bd 100644 --- a/Source/OBSCapture.cpp +++ b/Source/OBSCapture.cpp @@ -284,7 +284,20 @@ retryHookTestV2: } } - //------------------------------------------------------------- + //------------------------------------------------------------------ + + UINT format = AppConfig->GetInt(L"Audio Encoding", L"Format", 1); + + switch (format) { + case 0: sampleRateHz = 44100; break; + default: + case 1: sampleRateHz = 48000; break; + } + + Log(L"------------------------------------------"); + Log(L"Audio Format: %uhz", sampleRateHz); + + //------------------------------------------------------------------ AudioDeviceList playbackDevices; GetAudioDevices(playbackDevices, ADT_PLAYBACK); @@ -881,11 +894,11 @@ void OBS::EncodeAudioSegment(float *buffer, UINT numFrames, QWORD timestamp) } } -const int audioSamplesPerSec = 48000; -const int audioSampleSize = audioSamplesPerSec/100; - void OBS::MainAudioLoop() { + const unsigned int audioSamplesPerSec = App->GetSampleRateHz(); + const unsigned int audioSampleSize = audioSamplesPerSec/100; + DWORD taskID = 0; HANDLE hTask = AvSetMmThreadCharacteristics(TEXT("Pro Audio"), &taskID); diff --git a/Source/RTMPStuff.cpp b/Source/RTMPStuff.cpp index b869f003..437faf93 100644 --- a/Source/RTMPStuff.cpp +++ b/Source/RTMPStuff.cpp @@ -265,7 +265,7 @@ char* OBS::EncMetaData(char *enc, char *pend, bool bFLVFile) enc = AMF_EncodeNamedString(enc, pend, &av_audiocodecid, av_codecFourCC);//audioCodecID);// enc = AMF_EncodeNamedNumber(enc, pend, &av_audiodatarate, double(audioBitRate)); //ex. 128kb\s - enc = AMF_EncodeNamedNumber(enc, pend, &av_audiosamplerate, 48000.0); + enc = AMF_EncodeNamedNumber(enc, pend, &av_audiosamplerate, double(App->GetSampleRateHz())); enc = AMF_EncodeNamedNumber(enc, pend, &av_audiosamplesize, 16.0); enc = AMF_EncodeNamedNumber(enc, pend, &av_audiochannels, 2.0); enc = AMF_EncodeNamedBoolean(enc, pend, &av_stereo, true); diff --git a/Source/SettingsEncoding.cpp b/Source/SettingsEncoding.cpp index 0c8cecab..58fce6e5 100644 --- a/Source/SettingsEncoding.cpp +++ b/Source/SettingsEncoding.cpp @@ -213,7 +213,8 @@ INT_PTR SettingsEncoding::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam //-------------------------------------------- hwndTemp = GetDlgItem(hwnd, IDC_AUDIOFORMAT); - SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("48khz mono")); + //SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("48khz mono")); + SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("44.1khz stereo")); SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("48khz stereo")); LoadSettingComboInt(hwndTemp, TEXT("Audio Encoding"), TEXT("Format"), 1, 1);