60 friend class QSampleCache;
61 using SampleRate = QtMultimediaPrivate::SampleRate;
63 enum State : uint8_t {
68 using SharedSamplePromise = QSharedPointer<QPromise<q23::expected<QSample *, QSample::State>>>;
72 const QByteArray& data()
const { Q_ASSERT(state() == Ready);
return m_soundData; }
73 QSpan<
const float> dataAsFloatSpan()
const
75 Q_ASSERT(state() == Ready);
76 Q_ASSERT(m_audioFormat.sampleFormat() == QAudioFormat::Float);
77 return QSpan<
const float>(
reinterpret_cast<
const float *>(m_soundData.constData()),
78 m_audioFormat.framesForBytes(m_soundData.size())
79 * m_audioFormat.channelCount());
82 const QAudioFormat &format()
const
84 Q_ASSERT(state() == Ready);
87 qsizetype frameCount()
const
89 Q_ASSERT(state() == Ready);
90 return m_audioFormat.framesForBytes(m_soundData.size());
94 void setData(QByteArray, QAudioFormat);
96 QSample(QUrl url, QSampleCache *parent);
97 QSample(QUrl url, QSampleCache *parent, std::optional<SampleRate> targetSampleRate);
100 QSample(QByteArray data, QAudioFormat format)
101 : m_parent(
nullptr), m_soundData(std::move(data)), m_audioFormat(format), m_url(), m_state(Ready) {}
106 QSampleCache *m_parent;
107 QByteArray m_soundData;
108 QAudioFormat m_audioFormat;
110 const std::optional<SampleRate> m_targetSampleRate;
111 State m_state = State::Creating;
113 friend class QSampleCache;
123 friend class QSample;
125 enum class SampleSourceType : uint8_t {
131 static QSampleCache *instance();
133 explicit QSampleCache(QObject *parent =
nullptr);
134 ~QSampleCache() override;
136 QFuture<SharedSamplePtr>
137 requestSampleFuture(
const QUrl &, std::optional<
int> targetSampleRate = std::nullopt,
138 std::optional<SampleSourceType> forceSourceType = std::nullopt);
141 bool isCached(
const QUrl &url, std::optional<
int> targetSampleRate = std::nullopt)
const;
143 using SampleLoadResult = q23::expected<std::pair<QByteArray, QAudioFormat>, QSampleLoadError>;
145 static SampleLoadResult loadSample(QSpan<
const char>);
146 static SampleLoadResult loadSampleViaDecoder(std::variant<QUrl, QByteArray>);
147 static QFuture<SampleLoadResult> loadSampleAsyncViaDecoder(QByteArray);
150 std::unique_ptr<QIODevice> createStreamForSample(QSample &sample);
152 QThreadPool *threadPool();
156 using SharedSamplePromise = std::shared_ptr<QPromise<SharedSamplePtr>>;
158 mutable QRecursiveMutex m_mutex;
159 using SampleRate = QtMultimediaPrivate::SampleRate;
161 using SampleKey = std::pair<QUrl, std::optional<SampleRate>>;
162 std::map<SampleKey, WeakSamplePtr> m_loadedSamples;
163 std::map<SampleKey, std::pair<SharedSamplePtr, QList<SharedSamplePromise>>> m_pendingSamples;
165 void removeUnreferencedSample(
const QUrl &, std::optional<SampleRate> targetSampleRate);
168 static SampleLoadResult loadSample(
const QUrl &,
169 std::optional<SampleSourceType> = std::nullopt);
171 QThreadPool m_threadPool{
this };
174 QFuture<SampleLoadResult> loadSampleAsync(
const QUrl &,
175 std::optional<SampleSourceType> = std::nullopt);