24qreal sampleRateFactor()
41 static const qreal result = []() {
42 const auto sampleRateFactorStr =
43 qEnvironmentVariable(
"QT_MEDIA_PLAYER_AUDIO_SAMPLE_RATE_FACTOR");
45 const auto result = sampleRateFactorStr.toDouble(&ok);
46 return ok ? result : 1.;
54 explicit TrivialAudioFrameConverter(
const Frame &frame, QAudioFormat outputFormat,
57 int sampleRate = qRound(outputFormat.sampleRate() / playbackRate * sampleRateFactor());
58 outputFormat.setSampleRate(sampleRate);
59 m_converter = createResampler(frame, outputFormat);
62 QAudioBuffer convert(AVFrame *frame)
override {
return m_converter->resample(frame); }
65 std::unique_ptr<QFFmpegResampler> m_converter;
70 explicit PitchShiftingAudioFrameConverter(
const Frame &frame, QAudioFormat outputFormat,
72 : m_playbackRate{ playbackRate }
74 const QAudioFormat mediaFormat = QFFmpegMediaFormatInfo::audioFormatFromCodecParameters(
75 *frame.codecContext()->stream()->codecpar);
77 const QAudioFormat floatFormat = [&] {
78 QAudioFormat ret = mediaFormat;
79 ret.setSampleFormat(QAudioFormat::SampleFormat::Float);
83 m_toPCMDecoder = createResampler(frame, floatFormat);
85 m_pendingFractionalFrames = 0.f;
86 m_stretcher.presetDefault(mediaFormat.channelCount(), outputFormat.sampleRate());
88 const QAudioFormat pitchCompensatedFormat = [&] {
89 QAudioFormat ret = floatFormat;
90 ret.setSampleRate(outputFormat.sampleRate());
93 m_toOutputFormatConverter = std::make_unique<QFFmpegResampler>(
94 pitchCompensatedFormat, outputFormat, frame.startTime().get());
97 QAudioBuffer convert(AVFrame *frame)
override
99 using namespace QtPrivate;
102 QAudioBuffer wordConverted = m_toPCMDecoder->resample(frame);
105 int mediaFrameCount = wordConverted.frameCount();
106 float expectedNumberOfFrames = mediaFrameCount / m_playbackRate + m_pendingFractionalFrames;
107 int numberOfFullExpectedFrames = qFloor(expectedNumberOfFrames);
108 m_pendingFractionalFrames = expectedNumberOfFrames - numberOfFullExpectedFrames;
110 auto timeStretcherOutput = QAudioBuffer{
111 numberOfFullExpectedFrames,
112 wordConverted.format(),
117 QAudioBufferDeinterleaveAdaptor<
const float>{
121 QAudioBufferDeinterleaveAdaptor<
float>{
124 numberOfFullExpectedFrames);
127 QAudioBuffer outputBuffer = m_toOutputFormatConverter->resample(
128 timeStretcherOutput.constData<
const char>(), timeStretcherOutput.byteCount());
134 std::unique_ptr<QFFmpegResampler> m_toPCMDecoder;
135 signalsmith::stretch::SignalsmithStretch<
float> m_stretcher;
136 std::unique_ptr<QFFmpegResampler> m_toOutputFormatConverter;
137 float m_playbackRate;
138 float m_pendingFractionalFrames = 0.f;
146 const QAudioFormat &outputFormat)
149 frame.startTime().get());
155 return std::make_unique<TrivialAudioFrameConverter>(frame, outputFormat, playbackRate);
162 return std::make_unique<PitchShiftingAudioFrameConverter>(frame, outputFormat, playbackRate);