mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 875277 - Part 2: Implement WaveShaperNode.oversample - speex. r=ehsan
This commit is contained in:
parent
78371426cf
commit
dee2ecf218
@ -10,6 +10,7 @@
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "speex/speex_resampler.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -36,6 +37,121 @@ NS_INTERFACE_MAP_END_INHERITING(AudioNode)
|
||||
NS_IMPL_ADDREF_INHERITED(WaveShaperNode, AudioNode)
|
||||
NS_IMPL_RELEASE_INHERITED(WaveShaperNode, AudioNode)
|
||||
|
||||
static uint32_t ValueOf(OverSampleType aType)
|
||||
{
|
||||
switch (aType) {
|
||||
case OverSampleType::None: return 1;
|
||||
case OverSampleType::_2x: return 2;
|
||||
case OverSampleType::_4x: return 4;
|
||||
default:
|
||||
NS_NOTREACHED("We should never reach here");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
class Resampler
|
||||
{
|
||||
public:
|
||||
Resampler()
|
||||
: mType(OverSampleType::None)
|
||||
, mUpSampler(nullptr)
|
||||
, mDownSampler(nullptr)
|
||||
, mChannels(0)
|
||||
, mSampleRate(0)
|
||||
{
|
||||
}
|
||||
|
||||
~Resampler()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void Reset(uint32_t aChannels, TrackRate aSampleRate, OverSampleType aType)
|
||||
{
|
||||
if (aChannels == mChannels &&
|
||||
aSampleRate == mSampleRate &&
|
||||
aType == mType) {
|
||||
return;
|
||||
}
|
||||
|
||||
mChannels = aChannels;
|
||||
mSampleRate = aSampleRate;
|
||||
mType = aType;
|
||||
|
||||
Destroy();
|
||||
|
||||
if (aType == OverSampleType::None) {
|
||||
mBuffer.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
mUpSampler = speex_resampler_init(aChannels,
|
||||
aSampleRate,
|
||||
aSampleRate * ValueOf(aType),
|
||||
SPEEX_RESAMPLER_QUALITY_DEFAULT,
|
||||
nullptr);
|
||||
mDownSampler = speex_resampler_init(aChannels,
|
||||
aSampleRate * ValueOf(aType),
|
||||
aSampleRate,
|
||||
SPEEX_RESAMPLER_QUALITY_DEFAULT,
|
||||
nullptr);
|
||||
mBuffer.SetLength(WEBAUDIO_BLOCK_SIZE*ValueOf(aType));
|
||||
}
|
||||
|
||||
float* UpSample(uint32_t aChannel, const float* aInputData, uint32_t aBlocks)
|
||||
{
|
||||
uint32_t inSamples = WEBAUDIO_BLOCK_SIZE;
|
||||
uint32_t outSamples = WEBAUDIO_BLOCK_SIZE*aBlocks;
|
||||
float* outputData = mBuffer.Elements();
|
||||
|
||||
MOZ_ASSERT(mBuffer.Length() == outSamples);
|
||||
|
||||
speex_resampler_process_float(mUpSampler, aChannel,
|
||||
aInputData, &inSamples,
|
||||
outputData, &outSamples);
|
||||
|
||||
MOZ_ASSERT(inSamples == WEBAUDIO_BLOCK_SIZE && outSamples == WEBAUDIO_BLOCK_SIZE*aBlocks);
|
||||
|
||||
return outputData;
|
||||
}
|
||||
|
||||
void DownSample(uint32_t aChannel, float* aOutputData, uint32_t aBlocks)
|
||||
{
|
||||
uint32_t inSamples = WEBAUDIO_BLOCK_SIZE*aBlocks;
|
||||
uint32_t outSamples = WEBAUDIO_BLOCK_SIZE;
|
||||
const float* inputData = mBuffer.Elements();
|
||||
|
||||
MOZ_ASSERT(mBuffer.Length() == inSamples);
|
||||
|
||||
speex_resampler_process_float(mDownSampler, aChannel,
|
||||
inputData, &inSamples,
|
||||
aOutputData, &outSamples);
|
||||
|
||||
MOZ_ASSERT(inSamples == WEBAUDIO_BLOCK_SIZE*aBlocks && outSamples == WEBAUDIO_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
private:
|
||||
void Destroy()
|
||||
{
|
||||
if (mUpSampler) {
|
||||
speex_resampler_destroy(mUpSampler);
|
||||
mUpSampler = nullptr;
|
||||
}
|
||||
if (mDownSampler) {
|
||||
speex_resampler_destroy(mDownSampler);
|
||||
mDownSampler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OverSampleType mType;
|
||||
SpeexResamplerState* mUpSampler;
|
||||
SpeexResamplerState* mDownSampler;
|
||||
uint32_t mChannels;
|
||||
TrackRate mSampleRate;
|
||||
nsTArray<float> mBuffer;
|
||||
};
|
||||
|
||||
class WaveShaperNodeEngine : public AudioNodeEngine
|
||||
{
|
||||
public:
|
||||
@ -103,16 +219,24 @@ public:
|
||||
for (uint32_t i = 0; i < channelCount; ++i) {
|
||||
const float* inputBuffer = static_cast<const float*>(aInput.mChannelData[i]);
|
||||
float* outputBuffer = const_cast<float*> (static_cast<const float*>(aOutput->mChannelData[i]));
|
||||
float* sampleBuffer;
|
||||
|
||||
switch (mType) {
|
||||
case OverSampleType::None:
|
||||
mResampler.Reset(channelCount, aStream->SampleRate(), OverSampleType::None);
|
||||
ProcessCurve<1>(inputBuffer, outputBuffer);
|
||||
break;
|
||||
case OverSampleType::_2x:
|
||||
/* TODO: to be implemented */
|
||||
mResampler.Reset(channelCount, aStream->SampleRate(), OverSampleType::_2x);
|
||||
sampleBuffer = mResampler.UpSample(i, inputBuffer, 2);
|
||||
ProcessCurve<2>(sampleBuffer, sampleBuffer);
|
||||
mResampler.DownSample(i, outputBuffer, 2);
|
||||
break;
|
||||
case OverSampleType::_4x:
|
||||
/* TODO: to be implemented */
|
||||
mResampler.Reset(channelCount, aStream->SampleRate(), OverSampleType::_4x);
|
||||
sampleBuffer = mResampler.UpSample(i, inputBuffer, 4);
|
||||
ProcessCurve<4>(sampleBuffer, sampleBuffer);
|
||||
mResampler.DownSample(i, outputBuffer, 4);
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("We should never reach here");
|
||||
@ -123,6 +247,7 @@ public:
|
||||
private:
|
||||
nsTArray<float> mCurve;
|
||||
OverSampleType mType;
|
||||
Resampler mResampler;
|
||||
};
|
||||
|
||||
WaveShaperNode::WaveShaperNode(AudioContext* aContext)
|
||||
|
Loading…
Reference in New Issue
Block a user