Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/sanear.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Marsev <alex.marsev@gmail.com>2016-02-13 03:53:38 +0300
committerAlex Marsev <alex.marsev@gmail.com>2016-02-13 05:19:14 +0300
commit7bff1d22a2d5f8322e202f4741249ab2c5dde03a (patch)
tree0f2ccd46f5b87d2ca9dbf0334ccf4e885a3da476
parent643638f7a85bb8aab306ff9250ea1eba4e2331ae (diff)
Switch to new DspTempo2
That uses Rubber Band library.
-rw-r--r--dll/sanear.props2
-rw-r--r--dll/src/rubberband.vcxproj2
-rw-r--r--dll/src/rubberband.vcxproj.filters2
-rw-r--r--dll/src/sanear-dll.vcxproj23
-rw-r--r--sanear.vcxproj2
-rw-r--r--sanear.vcxproj.filters6
-rw-r--r--src/AudioRenderer.h3
-rw-r--r--src/DspTempo2.cpp129
-rw-r--r--src/DspTempo2.h43
9 files changed, 190 insertions, 22 deletions
diff --git a/dll/sanear.props b/dll/sanear.props
index 35da4c2..3775da9 100644
--- a/dll/sanear.props
+++ b/dll/sanear.props
@@ -3,7 +3,7 @@
<Import Project="$(SolutionDir)base.props" />
<ItemDefinitionGroup>
<ClCompile>
- <AdditionalIncludeDirectories>$(SolutionDir)src\baseclasses;$(SolutionDir)src\soxr\src;$(SolutionDir)src\libbs2b\src;$(SolutionDir)src\soundtouch\include;$(SolutionDir)src\zita-resampler\libs;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>$(SolutionDir)src\baseclasses;$(SolutionDir)src\soxr\src;$(SolutionDir)src\libbs2b\src;$(SolutionDir)src\soundtouch\include;$(SolutionDir)src\zita-resampler\libs;$(SolutionDir)src\rubberband\rubberband;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
</Project>
diff --git a/dll/src/rubberband.vcxproj b/dll/src/rubberband.vcxproj
index 52444b0..0d3bf2a 100644
--- a/dll/src/rubberband.vcxproj
+++ b/dll/src/rubberband.vcxproj
@@ -79,6 +79,8 @@
<ClCompile Include="rubberband\src\dsp\AudioCurveCalculator.cpp" />
<ClCompile Include="rubberband\src\dsp\FFT.cpp" />
<ClCompile Include="rubberband\src\dsp\Resampler.cpp" />
+ <ClCompile Include="rubberband\src\kissfft\kiss_fft.c" />
+ <ClCompile Include="rubberband\src\kissfft\kiss_fftr.c" />
<ClCompile Include="rubberband\src\rubberband-c.cpp" />
<ClCompile Include="rubberband\src\RubberBandStretcher.cpp" />
<ClCompile Include="rubberband\src\speex\resample.c" />
diff --git a/dll/src/rubberband.vcxproj.filters b/dll/src/rubberband.vcxproj.filters
index 13f556a..881c8c8 100644
--- a/dll/src/rubberband.vcxproj.filters
+++ b/dll/src/rubberband.vcxproj.filters
@@ -61,6 +61,8 @@
<ClCompile Include="rubberband\src\system\Thread.cpp">
<Filter>src</Filter>
</ClCompile>
+ <ClCompile Include="rubberband\src\kissfft\kiss_fft.c" />
+ <ClCompile Include="rubberband\src\kissfft\kiss_fftr.c" />
</ItemGroup>
<ItemGroup>
<Filter Include="src">
diff --git a/dll/src/sanear-dll.vcxproj b/dll/src/sanear-dll.vcxproj
index a720be8..46d98eb 100644
--- a/dll/src/sanear-dll.vcxproj
+++ b/dll/src/sanear-dll.vcxproj
@@ -89,35 +89,18 @@
</ProjectReference>
<ProjectReference Include="baseclasses.vcxproj">
<Project>{b8375339-1932-4cc0-ae5b-257672078e41}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
<ProjectReference Include="bs2b.vcxproj">
<Project>{c59b751c-f10d-4de0-b580-73cb03b27b6e}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
+ </ProjectReference>
+ <ProjectReference Include="rubberband.vcxproj">
+ <Project>{863e6128-1f58-4371-a282-0fcc62dff747}</Project>
</ProjectReference>
<ProjectReference Include="soundtouch.vcxproj">
<Project>{3c1b816a-645c-4e1f-a006-5c47263e59c5}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
<ProjectReference Include="soxr.vcxproj">
<Project>{2d2a92ff-1fb6-4926-affb-5e00d27939fc}</Project>
- <Private>false</Private>
- <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
- <CopyLocalSatelliteAssemblies>false</CopyLocalSatelliteAssemblies>
- <LinkLibraryDependencies>true</LinkLibraryDependencies>
- <UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
</ProjectReference>
</ItemGroup>
<ItemGroup>
diff --git a/sanear.vcxproj b/sanear.vcxproj
index 78f69f1..ee5c5b0 100644
--- a/sanear.vcxproj
+++ b/sanear.vcxproj
@@ -108,6 +108,7 @@
<ClInclude Include="src\DspCrossfeed.h" />
<ClInclude Include="src\DspDither.h" />
<ClInclude Include="src\DspFormat.h" />
+ <ClInclude Include="src\DspTempo2.h" />
<ClInclude Include="src\DspLimiter.h" />
<ClInclude Include="src\DspMatrix.h" />
<ClInclude Include="src\DspChunk.h" />
@@ -135,6 +136,7 @@
<ClCompile Include="src\DspBalance.cpp" />
<ClCompile Include="src\DspCrossfeed.cpp" />
<ClCompile Include="src\DspDither.cpp" />
+ <ClCompile Include="src\DspTempo2.cpp" />
<ClCompile Include="src\DspLimiter.cpp" />
<ClCompile Include="src\DspMatrix.cpp" />
<ClCompile Include="src\DspChunk.cpp" />
diff --git a/sanear.vcxproj.filters b/sanear.vcxproj.filters
index 47e99ea..7d8f18a 100644
--- a/sanear.vcxproj.filters
+++ b/sanear.vcxproj.filters
@@ -68,6 +68,9 @@
<ClCompile Include="src\AudioDeviceEvent.cpp">
<Filter>Device</Filter>
</ClCompile>
+ <ClCompile Include="src\DspTempo2.cpp">
+ <Filter>Processors</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\DspMatrix.h">
@@ -151,6 +154,9 @@
<ClInclude Include="src\AudioDeviceEvent.h">
<Filter>Device</Filter>
</ClInclude>
+ <ClInclude Include="src\DspTempo2.h">
+ <Filter>Processors</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="DirectShow">
diff --git a/src/AudioRenderer.h b/src/AudioRenderer.h
index 2761606..edfe416 100644
--- a/src/AudioRenderer.h
+++ b/src/AudioRenderer.h
@@ -9,6 +9,7 @@
#include "DspMatrix.h"
#include "DspRate.h"
#include "DspTempo.h"
+#include "DspTempo2.h"
#include "DspVolume.h"
#include "Interfaces.h"
#include "SampleCorrection.h"
@@ -115,7 +116,7 @@ namespace SaneAudioRenderer
DspMatrix m_dspMatrix;
DspRate m_dspRate;
- DspTempo m_dspTempo;
+ DspTempo2 m_dspTempo;
DspCrossfeed m_dspCrossfeed;
DspVolume m_dspVolume;
DspBalance m_dspBalance;
diff --git a/src/DspTempo2.cpp b/src/DspTempo2.cpp
new file mode 100644
index 0000000..e20db07
--- /dev/null
+++ b/src/DspTempo2.cpp
@@ -0,0 +1,129 @@
+#include "pch.h"
+#include "DspTempo2.h"
+
+namespace SaneAudioRenderer
+{
+ void DspTempo2::Initialize(double tempo, uint32_t rate, uint32_t channels)
+ {
+ m_stretcher = nullptr;
+
+ m_active = false;
+ m_finish = false;
+
+ m_rate = rate;
+ m_channels = channels;
+
+ if (tempo != 1.0)
+ {
+ try
+ {
+ auto options = RubberBand::RubberBandStretcher::OptionProcessRealTime |
+ RubberBand::RubberBandStretcher::OptionPitchHighQuality;
+
+ m_stretcher = std::make_unique<RubberBand::RubberBandStretcher>(rate, channels, options, 1.0 / tempo);
+
+ m_stretcher->setMaxProcessSize(rate);
+
+ m_active = true;
+ }
+ catch (std::bad_alloc&)
+ {
+ }
+ }
+ }
+
+ bool DspTempo2::Active()
+ {
+ return m_active;
+ }
+
+ void DspTempo2::Process(DspChunk& chunk)
+ {
+ if (!m_active || chunk.IsEmpty())
+ return;
+
+ assert(chunk.GetRate() == m_rate);
+ assert(chunk.GetChannelCount() == m_channels);
+
+ DspChunk::ToFloat(chunk);
+ m_stretcher->process(Deinterleave(chunk).data(), chunk.GetFrameCount(), m_finish);
+
+ size_t outputFrames = m_stretcher->available();
+
+ if (outputFrames > 0)
+ {
+
+ DspChunk output(DspFormat::Float, m_channels, outputFrames, m_rate);
+
+ size_t outputDone = m_stretcher->retrieve(MarkData(output).data(), outputFrames);
+ assert(outputDone == outputFrames);
+
+ Interleave(output);
+
+ chunk = std::move(output);
+ }
+ else
+ {
+ chunk = DspChunk();
+ }
+ }
+
+ void DspTempo2::Finish(DspChunk& chunk)
+ {
+ if (!m_active)
+ return;
+
+ assert(!m_finish);
+ m_finish = true;
+
+ Process(chunk);
+ }
+
+ DspTempo2::DeinterleavedData DspTempo2::MarkData(DspChunk& chunk)
+ {
+ assert(!chunk.IsEmpty());
+ assert(chunk.GetFormat() == DspFormat::Float);
+
+ DeinterleavedData data = {};
+
+ for (size_t i = 0; i < m_channels; i++)
+ data[i] = (float*)(chunk.GetData() + chunk.GetFormatSize() * chunk.GetFrameCount() * i);
+
+ return data;
+ }
+
+ DspTempo2::DeinterleavedData DspTempo2::Deinterleave(DspChunk& chunk)
+ {
+ assert(!chunk.IsEmpty());
+ assert(chunk.GetFormat() == DspFormat::Float);
+
+ DspChunk output(DspFormat::Float, m_channels, chunk.GetFrameCount(), m_rate);
+ DeinterleavedData outputData = MarkData(output);
+
+ float* inputData = (float*)chunk.GetData();
+
+ for (size_t i = 0, n = chunk.GetSampleCount(); i < n; i++)
+ outputData[i % m_channels][i / m_channels] = inputData[i];
+
+ chunk = std::move(output);
+
+ return outputData;
+ }
+
+ void DspTempo2::Interleave(DspChunk& chunk)
+ {
+ assert(!chunk.IsEmpty());
+ assert(chunk.GetFormat() == DspFormat::Float);
+
+ DspChunk output(DspFormat::Float, m_channels, chunk.GetFrameCount(), m_rate);
+ float* outputData = (float*)output.GetData();
+
+ DeinterleavedData inputData = MarkData(chunk);
+
+ for (size_t channel = 0; channel < m_channels; channel++)
+ for (size_t i = 0, n = chunk.GetFrameCount(); i < n; i++)
+ outputData[channel + i * m_channels] = inputData[channel][i];
+
+ chunk = std::move(output);
+ }
+}
diff --git a/src/DspTempo2.h b/src/DspTempo2.h
new file mode 100644
index 0000000..faf066d
--- /dev/null
+++ b/src/DspTempo2.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "DspBase.h"
+
+#include <RubberBandStretcher.h>
+
+namespace SaneAudioRenderer
+{
+ class DspTempo2 final
+ : public DspBase
+ {
+ public:
+
+ DspTempo2() = default;
+ DspTempo2(const DspTempo2&) = delete;
+ DspTempo2& operator=(const DspTempo2&) = delete;
+
+ void Initialize(double tempo, uint32_t rate, uint32_t channels);
+
+ std::wstring Name() override { return L"Tempo"; }
+
+ bool Active() override;
+
+ void Process(DspChunk& chunk) override;
+ void Finish(DspChunk& chunk) override;
+
+ private:
+
+ using DeinterleavedData = std::array<float*, 18>;
+
+ DeinterleavedData MarkData(DspChunk& chunk);
+ DeinterleavedData Deinterleave(DspChunk& chunk);
+ void Interleave(DspChunk& chunk);
+
+ std::unique_ptr<RubberBand::RubberBandStretcher> m_stretcher;
+
+ bool m_active = false;
+ bool m_finish = false;
+
+ uint32_t m_rate = 0;
+ uint32_t m_channels = 0;
+ };
+}