1 #pragma once 2 3 #include "audio/types.h" 4 #include "util/assert.h" 5 #include "util/macros.h" 6 #include "util/optional.h" 7 8 namespace mixxx { 9 10 namespace audio { 11 12 // Properties that characterize an uncompressed PCM audio signal. 13 class SignalInfo final { 14 // Properties 15 MIXXX_DECL_PROPERTY(ChannelCount, channelCount, ChannelCount) 16 MIXXX_DECL_PROPERTY(SampleRate, sampleRate, SampleRate) 17 18 public: 19 constexpr SignalInfo() = default; SignalInfo(ChannelCount channelCount,SampleRate sampleRate)20 SignalInfo( 21 ChannelCount channelCount, 22 SampleRate sampleRate) 23 : m_channelCount(channelCount), 24 m_sampleRate(sampleRate) { 25 } 26 SignalInfo(SignalInfo&&) = default; 27 SignalInfo(const SignalInfo&) = default; 28 /*non-virtual*/ ~SignalInfo() = default; 29 isValid()30 constexpr bool isValid() const { 31 return getChannelCount().isValid() && 32 getSampleRate().isValid(); 33 } 34 35 SignalInfo& operator=(SignalInfo&&) = default; 36 SignalInfo& operator=(const SignalInfo&) = default; 37 38 // Conversion: #samples / sample offset -> #frames / frame offset 39 // Only works for integer sample offsets on frame boundaries! samples2frames(SINT samples)40 SINT samples2frames(SINT samples) const { 41 DEBUG_ASSERT(getChannelCount().isValid()); 42 DEBUG_ASSERT(0 == (samples % getChannelCount())); 43 return samples / getChannelCount(); 44 } 45 46 // Conversion: #samples / sample offset -> #frames / frame offset samples2framesFractional(double samples)47 double samples2framesFractional(double samples) const { 48 DEBUG_ASSERT(getChannelCount().isValid()); 49 return samples / getChannelCount(); 50 } 51 52 // Conversion: #frames / frame offset -> #samples / sample offset frames2samples(SINT frames)53 SINT frames2samples(SINT frames) const { 54 DEBUG_ASSERT(getChannelCount().isValid()); 55 return frames * getChannelCount(); 56 } 57 58 // Conversion: #frames / frame offset -> second offset frames2secsFractional(double frames)59 double frames2secsFractional(double frames) const { 60 DEBUG_ASSERT(getSampleRate().isValid()); 61 return frames / getSampleRate(); 62 } 63 64 // Conversion: #frames / frame offset -> second offset frames2secs(SINT frames)65 double frames2secs(SINT frames) const { 66 return frames2secsFractional(static_cast<double>(frames)); 67 } 68 69 // Conversion: second offset -> #frames / frame offset secs2frames(double seconds)70 double secs2frames(double seconds) const { 71 DEBUG_ASSERT(getSampleRate().isValid()); 72 return seconds * getSampleRate(); 73 } 74 75 // Conversion: #frames / frame offset -> millisecond offset frames2millis(SINT frames)76 double frames2millis(SINT frames) const { 77 return frames2secs(frames) * 1000; 78 } 79 80 // Conversion: millisecond offset -> #frames / frame offset millis2frames(double milliseconds)81 double millis2frames(double milliseconds) const { 82 return secs2frames(milliseconds / 1000); 83 } 84 }; 85 86 bool operator==( 87 const SignalInfo& lhs, 88 const SignalInfo& rhs); 89 90 inline bool operator!=( 91 const SignalInfo& lhs, 92 const SignalInfo& rhs) { 93 return !(lhs == rhs); 94 } 95 96 QDebug operator<<(QDebug dbg, const SignalInfo& arg); 97 98 } // namespace audio 99 100 } // namespace mixxx 101 102 Q_DECLARE_METATYPE(mixxx::audio::SignalInfo) 103