Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
acolombier committed Apr 11, 2024
1 parent 7012b36 commit c9f2c2d
Show file tree
Hide file tree
Showing 22 changed files with 621 additions and 193 deletions.
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3455,7 +3455,15 @@ if (STEM)
target_compile_definitions(mixxx-lib PUBLIC __STEM__)
target_sources(mixxx-lib PRIVATE
src/sources/soundsourcestem.cpp
src/track/steminfoimporter.cpp
src/track/steminfo.cpp # TODO precompiled header?
)
if(QML)
target_compile_definitions(mixxx-qml-lib PUBLIC __STEM__)
target_sources(mixxx-qml-lib PRIVATE
src/qml/qmlstemsmodel.cpp
)
endif()
endif()

# Google PerfTools
Expand Down
138 changes: 112 additions & 26 deletions res/qml/EqColumn.qml
Original file line number Diff line number Diff line change
@@ -1,44 +1,130 @@
import "." as Skin
import QtQuick 2.12
import QtQuick.Shapes 1.12
import QtQuick.Layouts
import Mixxx 1.0 as Mixxx
import "Theme"

Column {
id: root

required property string group
property var player: Mixxx.PlayerManager.getPlayer(root.group)

spacing: 4
Mixxx.ControlProxy {
id: stemCountControl

Skin.EqKnob {
statusKey: "button_parameter3"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter3"
knob.color: Theme.eqHighColor
group: root.group
key: "stem_count"
}

Skin.EqKnob {
statusKey: "button_parameter2"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter2"
knob.color: Theme.eqMidColor
}
Row {
Column {
id: stem
spacing: 4
width: undefined
Repeater {
model: root.player.stemsModel

Skin.EqKnob {
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter1"
statusKey: "button_parameter1"
knob.color: Theme.eqLowColor
}
Row {
id: stem
required property int index
required property string label
required property color color

Rectangle {
id: stemRect
width: 56
height: 56
color: stem.color
radius: 5

Skin.ControlKnob {
id: knob
group: root.group
key: `stem_${index}_volume`
color: Theme.gainKnobColor
anchors.topMargin: 5
anchors.top: stemRect.top
anchors.horizontalCenter: stemRect.horizontalCenter

width: 36
height: 36
}
Text {
anchors.bottom: stemRect.bottom
anchors.horizontalCenter: stemRect.horizontalCenter
text: label
}
}
}
}
}
Column {
id: eq
spacing: 4
width: undefined
Skin.EqKnob {
statusKey: "button_parameter3"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter3"
knob.color: Theme.eqHighColor
}

Skin.EqKnob {
statusKey: "button_parameter2"
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter2"
knob.color: Theme.eqMidColor
}

Skin.EqKnob {
knob.group: "[EqualizerRack1_" + root.group + "_Effect1]"
knob.key: "parameter1"
statusKey: "button_parameter1"
knob.color: Theme.eqLowColor
}

Skin.EqKnob {
knob.group: "[QuickEffectRack1_" + root.group + "]"
knob.key: "super1"
statusGroup: "[QuickEffectRack1_" + root.group + "_Effect1]"
statusKey: "enabled"
knob.arcStyle: ShapePath.DashLine
knob.arcStylePattern: [2, 2]
knob.color: Theme.eqFxColor
}
}
states: [
State {
name: "eq"
when: stemCountControl.value == 0
PropertyChanges { target: stem; opacity: 0; width: 0}
},
State {
name: "stem"
when: stemCountControl.value != 0
PropertyChanges { target: eq; opacity: 0; width: 0 }
}
]

Skin.EqKnob {
knob.group: "[QuickEffectRack1_" + root.group + "]"
knob.key: "super1"
statusGroup: "[QuickEffectRack1_" + root.group + "_Effect1]"
statusKey: "enabled"
knob.arcStyle: ShapePath.DashLine
knob.arcStylePattern: [2, 2]
knob.color: Theme.eqFxColor
transitions: [
Transition {
from: "eq"
to: "stem"
ParallelAnimation {
PropertyAnimation { targets: [eq, stem]; properties: "opacity,width"; duration: 1000}
}
},
Transition {
from: "stem"
to: "eq"
ParallelAnimation {
PropertyAnimation { target: stem; properties: "opacity"; duration: 1000}
PropertyAnimation { target: eq; properties: "opacity"; duration: 1000}
}
}
]
}

Skin.OrientationToggleButton {
Expand Down
1 change: 1 addition & 0 deletions res/qml/Mixer.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "." as Skin
import Mixxx 1.0 as Mixxx
import QtQuick 2.12

Item {
Expand Down
5 changes: 3 additions & 2 deletions src/analyzer/analyzersilence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ SINT AnalyzerSilence::findLastSoundInChunk(std::span<const CSAMPLE> samples) {
// static
bool AnalyzerSilence::verifyFirstSound(
std::span<const CSAMPLE> samples,
mixxx::audio::FramePos firstSoundFrame) {
mixxx::audio::FramePos firstSoundFrame,
mixxx::audio::ChannelCount channelCount) {
const SINT firstSoundSample = findFirstSoundInChunk(samples);
if (firstSoundSample < static_cast<SINT>(samples.size())) {
return mixxx::audio::FramePos::fromEngineSamplePos(firstSoundSample)
return mixxx::audio::FramePos::fromEngineSamplePos(firstSoundSample, channelCount)
.toLowerFrameBoundary() == firstSoundFrame.toLowerFrameBoundary();
}
return false;
Expand Down
3 changes: 2 additions & 1 deletion src/analyzer/analyzersilence.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class AnalyzerSilence : public Analyzer {
/// last analysis run and is an indicator for file edits or decoder
/// changes/issues
static bool verifyFirstSound(std::span<const CSAMPLE> samples,
mixxx::audio::FramePos firstSoundFrame);
mixxx::audio::FramePos firstSoundFrame,
mixxx::audio::ChannelCount channelCount);

private:
UserSettingsPointer m_pConfig;
Expand Down
6 changes: 4 additions & 2 deletions src/engine/bufferscalers/enginebufferscale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@

#include "engine/engine.h"
#include "moc_enginebufferscale.cpp"
#include "soundio/soundmanagerconfig.h"

EngineBufferScale::EngineBufferScale()
: m_outputSignal(
mixxx::audio::SignalInfo(
mixxx::kEngineChannelCount,
mixxx::audio::SampleRate())),
SoundManagerConfig::kMixxxDefaultSampleRate)),
m_dBaseRate(1.0),
m_bSpeedAffectsPitch(false),
m_dTempoRatio(1.0),
m_dPitchRatio(1.0),
m_effectiveRate(1.0) {
DEBUG_ASSERT(!m_outputSignal.isValid());
DEBUG_ASSERT(m_outputSignal.isValid());
}

void EngineBufferScale::setOutputSignal(
mixxx::audio::SampleRate sampleRate,
mixxx::audio::ChannelCount channelCount) {
DEBUG_ASSERT(sampleRate.isValid());
DEBUG_ASSERT(channelCount.isValid());
bool changed = false;
if (sampleRate != m_outputSignal.getSampleRate()) {
m_outputSignal.setSampleRate(sampleRate);
Expand Down
3 changes: 2 additions & 1 deletion src/engine/cachingreader/cachingreaderworker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,8 @@ void CachingReaderWorker::verifyFirstSound(const CachingReaderChunk* pChunk,
mixxx::IndexRange::forward(end - 1, kNumSoundFrameToVerify));
// TODO support multi channel
if (AnalyzerSilence::verifyFirstSound(sampleBuffer.span(),
mixxx::audio::FramePos(1))) {
mixxx::audio::FramePos(1),
channelCount)) {
qDebug() << "First sound found at the previously stored position";
} else {
// This can happen in case of track edits or replacements, changed
Expand Down
38 changes: 34 additions & 4 deletions src/engine/channels/enginedeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
#include "engine/enginepregain.h"
#include "engine/enginevumeter.h"
#include "moc_enginedeck.cpp"
#include "track/track.h"
#include "util/sample.h"

namespace {
constexpr int kMaxSupportedStem = 4;
}

Check warning on line 15 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / clang-tidy

anonymous namespace not terminated with a closing comment [google-readability-namespace-comments]

EngineDeck::EngineDeck(
const ChannelHandleAndGroup& handleGroup,
UserSettingsPointer pConfig,
Expand All @@ -20,6 +25,7 @@ EngineDeck::EngineDeck(
/*isTalkoverChannel*/ false,
primaryDeck),
m_pConfig(pConfig),
m_pStemCount(std::make_unique<ControlObject>(ConfigKey(getGroup(), "stem_count"))),
m_pInputConfigured(new ControlObject(ConfigKey(getGroup(), "input_configured"))),
m_pPassing(new ControlPushButton(ConfigKey(getGroup(), "passthrough"))) {
m_pInputConfigured->setReadOnly();
Expand All @@ -36,6 +42,23 @@ EngineDeck::EngineDeck(

m_pPregain = new EnginePregain(getGroup());
m_pBuffer = new EngineBuffer(getGroup(), pConfig, this, pMixingEngine);
connect(m_pBuffer, &EngineBuffer::trackLoaded, this, &EngineDeck::slotTrackLoaded);

m_stemGain.reserve(kMaxSupportedStem);
for (int i = 0; i < kMaxSupportedStem; i++) {
m_stemGain.emplace_back(std::make_unique<ControlObject>(
ConfigKey(getGroup(), QString("stem_%1_volume").arg(i)),
true,
false,
false,
1.0));
}
}

void EngineDeck::slotTrackLoaded(TrackPointer pNewTrack,
TrackPointer) {
int stemCount = pNewTrack->getStemInfo().size();
m_pStemCount->set(stemCount);
}

EngineDeck::~EngineDeck() {
Expand All @@ -58,14 +81,21 @@ void EngineDeck::processStem(CSAMPLE* pOut, const int iBufferSize) {
for (int c = 0; c < stereoChannelCount; c++) {
// TODO(XXX): apply stem gain or skip muted stem
if (!c) {
pOut[2 * i] = m_stemBuffer.data()[2 * stereoChannelCount * i];
pOut[2 * i + 1] = m_stemBuffer.data()[2 * stereoChannelCount * i + 1];
pOut[2 * i] = m_stemBuffer.data()[2 * stereoChannelCount * i] *

Check failure on line 84 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 84 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
m_stemGain[c]->get();
pOut[2 * i + 1] =
m_stemBuffer.data()[2 * stereoChannelCount * i + 1] *

Check failure on line 87 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 87 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
m_stemGain[c]->get();
} else {
pOut[2 * i] += m_stemBuffer.data()[2 * stereoChannelCount * i + 2 * c];
pOut[2 * i] +=
m_stemBuffer
.data()[2 * stereoChannelCount * i + 2 * c] *
m_stemGain[c]->get();

Check failure on line 93 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 93 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
pOut[2 * i + 1] +=
m_stemBuffer
.data()[2 * stereoChannelCount * i +
2 * c + 1];
2 * c + 1] *
m_stemGain[c]->get();

Check failure on line 98 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / Ubuntu 22.04

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Werror=float-conversion]

Check warning on line 98 in src/engine/channels/enginedeck.cpp

View workflow job for this annotation

GitHub Actions / coverage

conversion from ‘double’ to ‘CSAMPLE’ {aka ‘float’} may change value [-Wfloat-conversion]
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/engine/channels/enginedeck.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "engine/channels/enginechannel.h"
#include "preferences/usersettings.h"
#include "soundio/soundmanagerutil.h"
#include "track/track_decl.h"
#include "util/samplebuffer.h"

class EnginePregain;
Expand Down Expand Up @@ -70,13 +71,16 @@ class EngineDeck : public EngineChannel, public AudioDestination {
public slots:
void slotPassthroughToggle(double v);
void slotPassthroughChangeRequest(double v);
void slotTrackLoaded(TrackPointer pNewTrack, TrackPointer);

private:
UserSettingsPointer m_pConfig;
EngineBuffer* m_pBuffer;
EnginePregain* m_pPregain;

mixxx::SampleBuffer m_stemBuffer;
std::unique_ptr<ControlObject> m_pStemCount;
std::vector<std::unique_ptr<ControlObject>> m_stemGain;

// Begin vinyl passthrough fields
QScopedPointer<ControlObject> m_pInputConfigured;
Expand Down
11 changes: 8 additions & 3 deletions src/engine/enginebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -884,13 +884,18 @@ void EngineBuffer::processTrackLocked(CSAMPLE* pOutput,
// (1.0 being normal rate. 2.0 plays at 2x speed -- 2 track seconds
// pass for every 1 real second). Depending on whether
// keylock is enabled, this is applied to either the rate or the tempo.
int stereoPairCount = m_channelCount / mixxx::audio::ChannelCount::stereo();
int outputBufferSize = iBufferSize,
stereoPairCount = m_channelCount / mixxx::audio::ChannelCount::stereo();
// The speed is calculated out of the buffer size for the stereo channel
// output, after mixing multi channel (stem) together
if (stereoPairCount > 1) {
outputBufferSize = iBufferSize / stereoPairCount;
}
double speed = m_pRateControl->calculateSpeed(
baserate,
tempoRatio,
paused,
// The speed is calculate out of the buffer size for the stereo channel output channel
iBufferSize / stereoPairCount,
outputBufferSize,
&is_scratching,
&is_reverse);

Expand Down
Loading

0 comments on commit c9f2c2d

Please sign in to comment.