我有一个基于桌面qt的应用程序,它从网络中获取声音流并使用QAudioOutput
播放它。我想为用户提供一个音量控制,这样他就可以减少音量。我的代码是这样的:
float volume_control = get_user_pref(); // user provided volume level {0.0,1.0}
for (;;) {
AVPacket *retrieved_pkt = get_decoded_packet_stream(); // from network stream
AVPacket *work_pkt
= change_volume(retrieved_pkt, volume_control); // this is what I need
// remaining code to play the work_pkt ...
}
我如何实现change_volume()
或有任何现成的功能,我可以使用?
编辑:按要求添加编解码器相关信息
QAudioFormat format;
format.setFrequency(44100);
format.setChannels(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
下面的代码运行正常。
// audio_buffer is a byte array of size data_size
// volume_level is a float between 0 (silent) and 1 (original volume)
int16_t * pcm_data = (int16_t*)(audio_buffer);
int32_t pcmval;
for (int ii = 0; ii < (data_size / 2); ii++) { // 16 bit, hence divided by 2
pcmval = pcm_data[ii] * volume_level ;
pcm_data[ii] = pcmval;
}
编辑:我认为这里有一个显著的优化范围,因为我的解决方案是计算密集型的。我想avcodec_decode_audio()
可以用来加速。
这是一个工作示例
QByteArray decreaseVolume(const QByteArray& audioData, qreal volumeLevel)
{
QByteArray modifiedAudioData(audioData.size(), ' ');
for (int i = 0; i < (audioData.size() / 2); i++)
{
int16_t sample = qFromLittleEndian<int16_t>(audioData.mid(i * 2, 2));
int32_t modifiedSample = sample * volumeLevel;
QByteArray modifiedBytes = QByteArray::fromRawData(reinterpret_cast<const char*>(&modifiedSample), 2);
modifiedAudioData.replace(i * 2, 2, modifiedBytes);
}
return modifiedAudioData;
}