Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
829ec47
Add types for properties of PCM audio signals and streams
uklotzde Mar 21, 2020
b384921
Use new PCM audio property types
uklotzde Mar 21, 2020
dadc2ca
Get rid of the Janus-headed AudioSignal base class
uklotzde Mar 22, 2020
64c884c
Defer import of CueInfo until stream properties are known
uklotzde Mar 25, 2020
c598edd
Fix wrong channel count for dual mono layout
uklotzde Mar 30, 2020
32ef6c8
Add samples/frames/seconds/milliseconds conversion functions
uklotzde Mar 30, 2020
a166aa2
Improve documentation of basic audio types
uklotzde Mar 30, 2020
3a1fcb3
Merge branch 'master' into audio_types
uklotzde Apr 1, 2020
3a40b0a
Merge branch 'master' into audio_types
uklotzde Apr 2, 2020
5407844
Clarify function usage comments
uklotzde Apr 2, 2020
c2bba36
Delete invalid debug assertion
uklotzde Apr 3, 2020
2a44461
Move debug assertion into base class
uklotzde Apr 3, 2020
ffc51f1
Add typedefs for value_t
uklotzde Apr 4, 2020
02e206c
Use "left-side const" according to coding style
uklotzde Apr 4, 2020
fed9a73
Set properties efficiently by passing a universal reference
uklotzde Apr 4, 2020
c8653f8
Merge branch 'master' of git@github.com:mixxxdj/mixxx.git into audio_…
uklotzde Apr 4, 2020
2e00d5e
Merge branch 'master' into audio_types
uklotzde Apr 5, 2020
cfc3fa3
Fix wrong debug assertion
uklotzde Apr 5, 2020
6d158e1
Merge branch 'master' of git@github.com:mixxxdj/mixxx.git into audio_…
uklotzde Apr 6, 2020
a3db3a3
Avoid string conversion for debug formatting
uklotzde Apr 6, 2020
8b88fb3
Rename getter and corresponding member
uklotzde Apr 6, 2020
2fec68c
Restore binding of replaygain_peak column
uklotzde Apr 6, 2020
0a2b1cd
Initialize Rubberband internals in constructor
uklotzde Apr 6, 2020
57cfe1e
Remove unused template declaration
uklotzde Apr 6, 2020
e3bd165
Replace template integer frame/sample counts with SINT
uklotzde Apr 6, 2020
6d4160c
Add remarks about frame boundary alignment requirement
uklotzde Apr 6, 2020
9c2e38c
Pre-allocate internal SoundTouch buffers in constructor
uklotzde Apr 6, 2020
55c760e
Delete error prone and ambiguous legacy sample conversion funcs
uklotzde Apr 8, 2020
de3ed12
Update comment and add warning
uklotzde Apr 8, 2020
ceb4a6b
Fix typo
uklotzde Apr 8, 2020
e0e0d14
Add const/non-const ptr property accessors
uklotzde Apr 8, 2020
23e6a11
Rename functions and members for importing CueInfos
uklotzde Apr 8, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/analyzer/plugins/analyzersoundtouchbeats.cpp
src/analyzer/plugins/buffering_utils.cpp
src/analyzer/trackanalysisscheduler.cpp
src/audio/types.cpp
src/audio/signalinfo.cpp
src/audio/streaminfo.cpp
src/control/control.cpp
src/control/controlaudiotaperpot.cpp
src/control/controlbehavior.cpp
Expand Down Expand Up @@ -561,7 +564,6 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/track/tracknumbers.cpp
src/track/trackrecord.cpp
src/track/trackref.cpp
src/util/audiosignal.cpp
src/util/autohidpi.cpp
src/util/battery/battery.cpp
src/util/cache.cpp
Expand Down
5 changes: 4 additions & 1 deletion build/depends.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,10 @@ def sources(self, build):
"src/analyzer/plugins/analyzerqueenmarykey.cpp",
"src/analyzer/plugins/buffering_utils.cpp",

"src/audio/types.cpp",
"src/audio/signalinfo.cpp",
"src/audio/streaminfo.cpp",

"src/controllers/controller.cpp",
"src/controllers/controllerdebug.cpp",
"src/controllers/controllerengine.cpp",
Expand Down Expand Up @@ -1311,7 +1315,6 @@ def sources(self, build):
"src/util/logger.cpp",
"src/util/logging.cpp",
"src/util/cmdlineargs.cpp",
"src/util/audiosignal.cpp",
"src/util/widgethider.cpp",
"src/util/autohidpi.cpp",
"src/util/screensaver.cpp",
Expand Down
6 changes: 4 additions & 2 deletions src/analyzer/analyzerthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ void AnalyzerThread::doRun() {
// Make sure not to short-circuit initialize(...)
if (analyzer.initialize(
m_currentTrack,
audioSource->sampleRate(),
audioSource->getSignalInfo().getSampleRate(),
audioSource->frameLength() * mixxx::kAnalysisChannels)) {
processTrack = true;
}
Expand Down Expand Up @@ -226,7 +226,9 @@ AnalyzerThread::AnalysisResult AnalyzerThread::analyzeAudioSource(
mixxx::AudioSourceStereoProxy audioSourceProxy(
audioSource,
mixxx::kAnalysisFramesPerChunk);
DEBUG_ASSERT(audioSourceProxy.channelCount() == mixxx::kAnalysisChannels);
DEBUG_ASSERT(
audioSourceProxy.getSignalInfo().getChannelCount() ==
mixxx::kAnalysisChannels);

// Analysis starts now
emitBusyProgress(kAnalyzerProgressNone);
Expand Down
3 changes: 1 addition & 2 deletions src/analyzer/constants.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#pragma once

#include "engine/engine.h"
#include "util/audiosignal.h"

namespace mixxx {

// Analysis is done in blocks to avoid dynamic allocation of memory
// depending on the track length. A block size of 4096 frames per block
// seems to do fine. Signal processing during analysis uses the same,
// fixed number of channels like the engine does, usually 2 = stereo.
constexpr mixxx::AudioSignal::ChannelCount kAnalysisChannels = mixxx::kEngineChannelCount;
constexpr audio::ChannelCount kAnalysisChannels = mixxx::kEngineChannelCount;
constexpr SINT kAnalysisFramesPerChunk = 4096;
constexpr SINT kAnalysisSamplesPerChunk =
kAnalysisFramesPerChunk * kAnalysisChannels;
Expand Down
27 changes: 27 additions & 0 deletions src/audio/signalinfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "audio/signalinfo.h"

namespace mixxx {

namespace audio {

bool operator==(
const SignalInfo& lhs,
const SignalInfo& rhs) {
return lhs.getChannelCount() == rhs.getChannelCount() &&
lhs.getSampleLayout() == rhs.getSampleLayout() &&
lhs.getSampleRate() == rhs.getSampleRate();
}

QDebug
operator<<(QDebug dbg, const SignalInfo& arg) {
dbg << "SignalInfo{";
arg.dbgChannelCount(dbg);
arg.dbgSampleLayout(dbg);
arg.dbgSampleRate(dbg);
dbg << '}';
return dbg;
}

} // namespace audio

} // namespace mixxx
99 changes: 99 additions & 0 deletions src/audio/signalinfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#pragma once

#include "audio/types.h"
#include "util/assert.h"
#include "util/macros.h"
#include "util/optional.h"

namespace mixxx {

namespace audio {

// Properties that characterize an uncompressed PCM audio signal.
class SignalInfo final {
// Properties
PROPERTY_SET_BYVAL_GET_BYREF(ChannelCount, channelCount, ChannelCount)
PROPERTY_SET_BYVAL_GET_BYREF(SampleRate, sampleRate, SampleRate)
PROPERTY_SET_BYVAL_GET_BYREF(OptionalSampleLayout, sampleLayout, SampleLayout)

public:
constexpr SignalInfo() = default;
constexpr explicit SignalInfo(
OptionalSampleLayout sampleLayout)
: m_sampleLayout(sampleLayout) {
}
SignalInfo(
ChannelCount channelCount,
SampleRate sampleRate,
OptionalSampleLayout sampleLayout = std::nullopt)
: m_channelCount(channelCount),
m_sampleRate(sampleRate),
m_sampleLayout(sampleLayout) {
}
SignalInfo(SignalInfo&&) = default;
SignalInfo(const SignalInfo&) = default;
/*non-virtual*/ ~SignalInfo() = default;

constexpr bool isValid() const {
return getChannelCount().isValid() &&
getSampleLayout() &&
getSampleRate().isValid();
}

SignalInfo& operator=(SignalInfo&&) = default;
SignalInfo& operator=(const SignalInfo&) = default;

// Conversion: #samples / sample offset -> #frames / frame offset
Comment thread
uklotzde marked this conversation as resolved.
// Only works for integer sample offsets on frame boundaries!
SINT samples2frames(SINT samples) const {
DEBUG_ASSERT(getChannelCount().isValid());
DEBUG_ASSERT(0 == (samples % getChannelCount()));
return samples / getChannelCount();
}

// Conversion: #frames / frame offset -> #samples / sample offset
SINT frames2samples(SINT frames) const {
DEBUG_ASSERT(getChannelCount().isValid());
return frames * getChannelCount();
}

// Conversion: #frames / frame offset -> second offset
double frames2secs(SINT frames) const {
DEBUG_ASSERT(getSampleRate().isValid());
return static_cast<double>(frames) / getSampleRate();
}

// Conversion: second offset -> #frames / frame offset
double secs2frames(double seconds) const {
DEBUG_ASSERT(getSampleRate().isValid());
return seconds * getSampleRate();
}

// Conversion: #frames / frame offset -> millisecond offset
double frames2millis(SINT frames) const {
return frames2secs(frames) * 1000;
}

// Conversion: millisecond offset -> #frames / frame offset
double millis2frames(double milliseconds) const {
return secs2frames(milliseconds / 1000);
}
};

bool operator==(
const SignalInfo& lhs,
const SignalInfo& rhs);

inline bool operator!=(
const SignalInfo& lhs,
const SignalInfo& rhs) {
return !(lhs == rhs);
}

QDebug operator<<(QDebug dbg, const SignalInfo& arg);

} // namespace audio

} // namespace mixxx

Q_DECLARE_METATYPE(mixxx::audio::SignalInfo)
27 changes: 27 additions & 0 deletions src/audio/streaminfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "audio/streaminfo.h"

namespace mixxx {

namespace audio {

bool operator==(
const StreamInfo& lhs,
const StreamInfo& rhs) {
return lhs.getSignalInfo() == rhs.getSignalInfo() &&
lhs.getBitrate() == rhs.getBitrate() &&
lhs.getDuration() == rhs.getDuration();
}

QDebug
operator<<(QDebug dbg, const StreamInfo& arg) {
Comment thread
uklotzde marked this conversation as resolved.
dbg << "StreamInfo{";
arg.dbgSignalInfo(dbg);
arg.dbgBitrate(dbg);
arg.dbgDuration(dbg);
dbg << '}';
return dbg;
}

} // namespace audio

} // namespace mixxx
64 changes: 64 additions & 0 deletions src/audio/streaminfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once

#include "audio/signalinfo.h"
#include "util/duration.h"

namespace mixxx {

namespace audio {

// Properties that characterize a (compressed) PCM audio stream.
//
// Currently we assume that every stream has a finite duration
// that is known upfront!
class StreamInfo final {
// Properties
PROPERTY_SET_BYVAL_GET_BYREF(SignalInfo, signalInfo, SignalInfo)
PROPERTY_SET_BYVAL_GET_BYREF(Bitrate, bitrate, Bitrate)
PROPERTY_SET_BYVAL_GET_BYREF(Duration, duration, Duration)

public:
constexpr StreamInfo() = default;
constexpr explicit StreamInfo(
const SignalInfo& signalInfo)
: m_signalInfo(signalInfo) {
}
constexpr StreamInfo(
const SignalInfo& signalInfo,
Bitrate bitrate,
Duration duration)
: m_signalInfo(signalInfo),
m_bitrate(bitrate),
m_duration(duration) {
}
StreamInfo(StreamInfo&&) = default;
StreamInfo(const StreamInfo&) = default;
/*non-virtual*/ ~StreamInfo() = default;

constexpr bool isValid() const {
return getSignalInfo().isValid() &&
getBitrate().isValid() &&
(getDuration() > Duration::empty());
}

StreamInfo& operator=(StreamInfo&&) = default;
StreamInfo& operator=(const StreamInfo&) = default;
};

bool operator==(
const StreamInfo& lhs,
const StreamInfo& rhs);

inline bool operator!=(
const StreamInfo& lhs,
const StreamInfo& rhs) {
return !(lhs == rhs);
}

QDebug operator<<(QDebug dbg, const StreamInfo& arg);

} // namespace audio

} // namespace mixxx

Q_DECLARE_METATYPE(mixxx::audio::StreamInfo)
45 changes: 45 additions & 0 deletions src/audio/types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "audio/types.h"

namespace mixxx {

namespace audio {

QDebug operator<<(QDebug dbg, ChannelLayout arg) {
switch (arg) {
case ChannelLayout::Mono:
return dbg << "Mono";
case ChannelLayout::DualMono:
return dbg << "DualMono";
case ChannelLayout::Stereo:
return dbg << "Stereo";
}
DEBUG_ASSERT(!"unreachable code");
return dbg;
}

QDebug operator<<(QDebug dbg, SampleLayout arg) {
switch (arg) {
case SampleLayout::Planar:
return dbg << "Planar";
case SampleLayout::Interleaved:
return dbg << "Interleaved";
}
DEBUG_ASSERT(!"unreachable code");
return dbg;
}

QDebug operator<<(QDebug dbg, SampleRate arg) {
return dbg
<< static_cast<SampleRate::value_t>(arg)
<< SampleRate::unit();
}

QDebug operator<<(QDebug dbg, Bitrate arg) {
return dbg
<< static_cast<Bitrate::value_t>(arg)
<< Bitrate::unit();
}

} // namespace audio

} // namespace mixxx
Loading