Allow the option to select sample rate to stream at rather than have it hard coded to 48000hz
This commit is contained in:
parent
8fd7282cb8
commit
3520b15ca4
@ -74,8 +74,7 @@ void NoiseGateFilter::ApplyNoiseGate(float *buffer, int totalFloats)
|
|||||||
if(totalFloats % 2)
|
if(totalFloats % 2)
|
||||||
return; // Odd number of samples
|
return; // Odd number of samples
|
||||||
|
|
||||||
// OBS is currently hard-coded to 48ksps
|
const float SAMPLE_RATE_F = float(OBSGetSampleRateHz());
|
||||||
const float SAMPLE_RATE_F = 48000.0f;
|
|
||||||
const float dtPerSample = 1.0f / SAMPLE_RATE_F;
|
const float dtPerSample = 1.0f / SAMPLE_RATE_F;
|
||||||
|
|
||||||
// Convert configuration times into per-sample amounts
|
// 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);
|
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
|
// 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
|
// threshold if the previous peak crosses the open threshold.
|
||||||
// samples between peaks.
|
|
||||||
const float thresholdDiff = parent->openThreshold - parent->closeThreshold;
|
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;
|
const float decayRate = thresholdDiff / minDecayPeriod;
|
||||||
|
|
||||||
// We can't use SSE as the processing of each sample depends on the processed
|
// We can't use SSE as the processing of each sample depends on the processed
|
||||||
|
2
OBS.rc
2
OBS.rc
@ -126,7 +126,7 @@ BEGIN
|
|||||||
RTEXT "Settings.Encoding.Audio.Bitrate",IDC_STATIC,221,85,128,8
|
RTEXT "Settings.Encoding.Audio.Bitrate",IDC_STATIC,221,85,128,8
|
||||||
COMBOBOX IDC_AUDIOBITRATE,354,83,61,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
COMBOBOX IDC_AUDIOBITRATE,354,83,61,62,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
RTEXT "Settings.Encoding.Audio.Format",IDC_STATIC,10,101,138,8
|
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
|
LTEXT "Settings.Info",IDC_INFO,4,122,417,37,NOT WS_VISIBLE
|
||||||
END
|
END
|
||||||
|
|
||||||
|
@ -141,4 +141,6 @@ void OBSGetCurMicVolumeStats(float *rms, float *max, float *peak) {API->Ge
|
|||||||
void OBSAddSettingsPane(SettingsPane *pane) {API->AddSettingsPane(pane);}
|
void OBSAddSettingsPane(SettingsPane *pane) {API->AddSettingsPane(pane);}
|
||||||
void OBSRemoveSettingsPane(SettingsPane *pane) {API->RemoveSettingsPane(pane);}
|
void OBSRemoveSettingsPane(SettingsPane *pane) {API->RemoveSettingsPane(pane);}
|
||||||
|
|
||||||
UINT OBSGetAPIVersion() {return 0x0100;}
|
UINT OBSGetAPIVersion() {return 0x0101;}
|
||||||
|
|
||||||
|
UINT OBSGetSampleRateHz() {return API->GetSampleRateHz();}
|
||||||
|
@ -172,6 +172,8 @@ public:
|
|||||||
virtual Vect2 MapFrameToWindowSize(Vect2 frameSize) const=0;
|
virtual Vect2 MapFrameToWindowSize(Vect2 frameSize) const=0;
|
||||||
virtual Vect2 GetWindowToFrameScale() const=0;
|
virtual Vect2 GetWindowToFrameScale() const=0;
|
||||||
virtual Vect2 GetFrameToWindowScale() const=0;
|
virtual Vect2 GetFrameToWindowScale() const=0;
|
||||||
|
|
||||||
|
virtual UINT GetSampleRateHz() const=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
BASE_EXPORT extern APIInterface *API;
|
BASE_EXPORT extern APIInterface *API;
|
||||||
@ -286,3 +288,5 @@ BASE_EXPORT void OBSRemoveSettingsPane(SettingsPane *pane);
|
|||||||
|
|
||||||
/** gets API version. version is formatted: 0xMMmm */
|
/** gets API version. version is formatted: 0xMMmm */
|
||||||
BASE_EXPORT UINT OBSGetAPIVersion();
|
BASE_EXPORT UINT OBSGetAPIVersion();
|
||||||
|
|
||||||
|
BASE_EXPORT UINT OBSGetSampleRateHz();
|
||||||
|
@ -87,7 +87,9 @@ void AudioSource::InitAudioData(bool bFloat, UINT channels, UINT samplesPerSec,
|
|||||||
|
|
||||||
//-----------------------------
|
//-----------------------------
|
||||||
|
|
||||||
if(inputSamplesPerSec != 48000)
|
UINT sampleRateHz = OBSGetSampleRateHz();
|
||||||
|
|
||||||
|
if(inputSamplesPerSec != sampleRateHz)
|
||||||
{
|
{
|
||||||
int errVal;
|
int errVal;
|
||||||
|
|
||||||
@ -96,12 +98,11 @@ void AudioSource::InitAudioData(bool bFloat, UINT channels, UINT samplesPerSec,
|
|||||||
if(!resampler)
|
if(!resampler)
|
||||||
CrashError(TEXT("AudioSource::InitAudioData: Could not initiate resampler"));
|
CrashError(TEXT("AudioSource::InitAudioData: Could not initiate resampler"));
|
||||||
|
|
||||||
resampleRatio = 48000.0 / double(inputSamplesPerSec);
|
resampleRatio = double(sampleRateHz) / double(inputSamplesPerSec);
|
||||||
bResample = true;
|
bResample = true;
|
||||||
|
|
||||||
//----------------------------------------------------
|
//----------------------------------------------------
|
||||||
// hack to get rid of that weird first quirky resampled packet size
|
// 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;
|
SRC_DATA data;
|
||||||
data.src_ratio = resampleRatio;
|
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();
|
*buffer = outputBuffer.Array();
|
||||||
|
|
||||||
|
@ -539,6 +539,8 @@ public:
|
|||||||
|
|
||||||
virtual void AddSettingsPane(SettingsPane *pane) {App->AddSettingsPane(pane);}
|
virtual void AddSettingsPane(SettingsPane *pane) {App->AddSettingsPane(pane);}
|
||||||
virtual void RemoveSettingsPane(SettingsPane *pane) {App->RemoveSettingsPane(pane);}
|
virtual void RemoveSettingsPane(SettingsPane *pane) {App->RemoveSettingsPane(pane);}
|
||||||
|
|
||||||
|
virtual UINT GetSampleRateHz() const {return App->GetSampleRateHz();}
|
||||||
};
|
};
|
||||||
|
|
||||||
APIInterface* CreateOBSApiInterface()
|
APIInterface* CreateOBSApiInterface()
|
||||||
|
@ -46,7 +46,7 @@ public:
|
|||||||
{
|
{
|
||||||
curBitRate = bitRate;
|
curBitRate = bitRate;
|
||||||
|
|
||||||
faac = faacEncOpen(48000, 2, &numReadSamples, &outputSize);
|
faac = faacEncOpen(App->GetSampleRateHz(), 2, &numReadSamples, &outputSize);
|
||||||
|
|
||||||
//Log(TEXT("numReadSamples: %d"), numReadSamples);
|
//Log(TEXT("numReadSamples: %d"), numReadSamples);
|
||||||
aacBuffer.SetSize(outputSize+2);
|
aacBuffer.SetSize(outputSize+2);
|
||||||
@ -155,7 +155,7 @@ public:
|
|||||||
inputBuffer.RemoveRange(0, numReadSamples);
|
inputBuffer.RemoveRange(0, numReadSamples);
|
||||||
|
|
||||||
bufferedTimestamps << curEncodeTimestamp;
|
bufferedTimestamps << curEncodeTimestamp;
|
||||||
curEncodeTimestamp = curTimestamp + (((numReadSamples-lastSampleSize)/2)/48);
|
curEncodeTimestamp = curTimestamp + (((numReadSamples-lastSampleSize)/2)*1000/App->GetSampleRateHz());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret > 0;
|
return ret > 0;
|
||||||
|
@ -59,8 +59,8 @@ public:
|
|||||||
if(!lgf)
|
if(!lgf)
|
||||||
CrashError(TEXT("Unable to open mp3 encoder"));
|
CrashError(TEXT("Unable to open mp3 encoder"));
|
||||||
|
|
||||||
lame_set_in_samplerate(lgf, 48000);
|
lame_set_in_samplerate(lgf, App->GetSampleRateHz());
|
||||||
lame_set_out_samplerate(lgf, 48000);
|
lame_set_out_samplerate(lgf, App->GetSampleRateHz());
|
||||||
lame_set_num_channels(lgf, 2);
|
lame_set_num_channels(lgf, 2);
|
||||||
lame_set_mode(lgf, STEREO);
|
lame_set_mode(lgf, STEREO);
|
||||||
lame_set_disable_reservoir(lgf, TRUE); //bit reservoir has to be disabled for seamless streaming
|
lame_set_disable_reservoir(lgf, TRUE); //bit reservoir has to be disabled for seamless streaming
|
||||||
@ -102,7 +102,7 @@ public:
|
|||||||
frameCounter -= outputFrameSize;
|
frameCounter -= outputFrameSize;
|
||||||
|
|
||||||
bufferedTimestamps << curEncodeTimestamp;
|
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);
|
int ret = lame_encode_buffer_interleaved_ieee_float(lgf, (float*)input, numInputFrames, MP3OutputBuffer.Array()+1, dwMP3MaxSize);
|
||||||
|
@ -57,7 +57,7 @@ struct MP4AudioFrameInfo
|
|||||||
|
|
||||||
inline UINT64 ConvertToAudioTime(DWORD timestamp, UINT64 minVal)
|
inline UINT64 ConvertToAudioTime(DWORD timestamp, UINT64 minVal)
|
||||||
{
|
{
|
||||||
UINT val = UINT64(timestamp)*48000/1000;
|
UINT val = UINT64(timestamp)*App->GetSampleRateHz()/1000;
|
||||||
return MAX(val, minVal);
|
return MAX(val, minVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +303,7 @@ public:
|
|||||||
|
|
||||||
DWORD macTime = fastHtonl(DWORD(GetMacTime()));
|
DWORD macTime = fastHtonl(DWORD(GetMacTime()));
|
||||||
UINT videoDuration = fastHtonl(lastVideoTimestamp + App->GetFrameTime());
|
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;
|
UINT width, height;
|
||||||
App->GetOutputSize(width, height);
|
App->GetOutputSize(width, height);
|
||||||
|
|
||||||
@ -453,7 +453,7 @@ public:
|
|||||||
output.OutputDword(0); //version and flags (none)
|
output.OutputDword(0); //version and flags (none)
|
||||||
output.OutputDword(macTime); //creation time
|
output.OutputDword(macTime); //creation time
|
||||||
output.OutputDword(macTime); //modified 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(audioUnitDuration);
|
||||||
output.OutputDword(bMP3 ? DWORD_BE(0x55c40000) : DWORD_BE(0x15c70000));
|
output.OutputDword(bMP3 ? DWORD_BE(0x55c40000) : DWORD_BE(0x15c70000));
|
||||||
PopBox(output); //mdhd
|
PopBox(output); //mdhd
|
||||||
@ -495,7 +495,7 @@ public:
|
|||||||
output.OutputWord(WORD_BE(16)); //sample size
|
output.OutputWord(WORD_BE(16)); //sample size
|
||||||
output.OutputWord(0); //quicktime audio compression id
|
output.OutputWord(0); //quicktime audio compression id
|
||||||
output.OutputWord(0); //quicktime audio packet size
|
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'));
|
PushBox(output, DWORD_BE('esds'));
|
||||||
output.OutputDword(0); //version and flags (none)
|
output.OutputDword(0); //version and flags (none)
|
||||||
output.OutputByte(3); //ES descriptor type
|
output.OutputByte(3); //ES descriptor type
|
||||||
|
@ -499,6 +499,8 @@ class OBS
|
|||||||
AudioSource *micAudio;
|
AudioSource *micAudio;
|
||||||
List<AudioSource*> auxAudioSources;
|
List<AudioSource*> auxAudioSources;
|
||||||
|
|
||||||
|
UINT sampleRateHz;
|
||||||
|
|
||||||
AudioEncoder *audioEncoder;
|
AudioEncoder *audioEncoder;
|
||||||
|
|
||||||
//---------------------------------------------------
|
//---------------------------------------------------
|
||||||
@ -913,6 +915,8 @@ public:
|
|||||||
OSLeaveMutex(hAuxAudioMutex);
|
OSLeaveMutex(hAuxAudioMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline UINT GetSampleRateHz() const {return sampleRateHz;}
|
||||||
|
|
||||||
inline QWORD GetAudioTime() const {return latestAudioTime;}
|
inline QWORD GetAudioTime() const {return latestAudioTime;}
|
||||||
inline QWORD GetVideoTime() const {return latestVideoTime;}
|
inline QWORD GetVideoTime() const {return latestVideoTime;}
|
||||||
|
|
||||||
|
@ -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;
|
AudioDeviceList playbackDevices;
|
||||||
GetAudioDevices(playbackDevices, ADT_PLAYBACK);
|
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()
|
void OBS::MainAudioLoop()
|
||||||
{
|
{
|
||||||
|
const unsigned int audioSamplesPerSec = App->GetSampleRateHz();
|
||||||
|
const unsigned int audioSampleSize = audioSamplesPerSec/100;
|
||||||
|
|
||||||
DWORD taskID = 0;
|
DWORD taskID = 0;
|
||||||
HANDLE hTask = AvSetMmThreadCharacteristics(TEXT("Pro Audio"), &taskID);
|
HANDLE hTask = AvSetMmThreadCharacteristics(TEXT("Pro Audio"), &taskID);
|
||||||
|
|
||||||
|
@ -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_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_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_audiosamplesize, 16.0);
|
||||||
enc = AMF_EncodeNamedNumber(enc, pend, &av_audiochannels, 2.0);
|
enc = AMF_EncodeNamedNumber(enc, pend, &av_audiochannels, 2.0);
|
||||||
enc = AMF_EncodeNamedBoolean(enc, pend, &av_stereo, true);
|
enc = AMF_EncodeNamedBoolean(enc, pend, &av_stereo, true);
|
||||||
|
@ -213,7 +213,8 @@ INT_PTR SettingsEncoding::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam
|
|||||||
//--------------------------------------------
|
//--------------------------------------------
|
||||||
|
|
||||||
hwndTemp = GetDlgItem(hwnd, IDC_AUDIOFORMAT);
|
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"));
|
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("48khz stereo"));
|
||||||
|
|
||||||
LoadSettingComboInt(hwndTemp, TEXT("Audio Encoding"), TEXT("Format"), 1, 1);
|
LoadSettingComboInt(hwndTemp, TEXT("Audio Encoding"), TEXT("Format"), 1, 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user