收到消息“有缓冲区下溢!”每次写完这个简单的程序之后。
Beep.hpp:
0.028171725121151
Beep.cpp:
func textView(_ textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
/* perform your own custom actions here */
print(URL)
return true // return true if you still want UIAlertController to pop up
}
main.cpp中:
#pragma once
#include <QTimer>
#include <QAudioOutput>
class Beep: public QObject
{
Q_OBJECT
public:
explicit Beep();
virtual ~Beep();
void onTimer();
private:
QAudioOutput m_out;
QIODevice *m_outDev;
QTimer m_timer;
};
这个测试程序只是用零写缓冲区。有了实际数据,就会出现破解声。
写更多数据或更改时间会让情况变得更糟。这段代码出了什么问题?
答案 0 :(得分:0)
使用计时器是错误的方法。
使用notify()信号
void AudioManager::init_audio(AudioManager *mgr) {
if (mgr->stream_id == -1) return;
mgr->audio_format.setSampleRate(mgr->context->time_base.den);
mgr->audio_format.setSampleSize(16);
mgr->audio_format.setChannelCount(2);
mgr->audio_format.setCodec("audio/pcm");
mgr->audio_format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(mgr->audio_format)) {
mgr->audio_format = info.nearestFormat(mgr->audio_format);
}
mgr->audio_out = new QAudioOutput(mgr->audio_format, nullptr);
mgr->audio_out->setNotifyInterval(15);
mgr->audio_out->setBufferSize(mgr->context->time_base.den * 4); // 1 second worth of stereo data
connect(mgr->audio_out, SIGNAL(notify()), mgr, SLOT(audio_out_notify()));
connect(mgr->audio_out, SIGNAL(stateChanged(QAudio::State)), mgr, SLOT(audio_out_state_changed(QAudio::State)));
qreal volume_out = (qreal)parent->volume / 100.0f;
mgr->audio_out->setVolume(volume_out);
mgr->audio_out_device = mgr->audio_out->start();
}
当音频播放需要更多数据时,将调用此方法
void AudioManager::audio_out_notify() {
qDebug() << "Audio notify";
check_audio_playback();
}
下面的大部分代码都是无关紧要的,但也称为音频已经停止播放。
void AudioManager::check_audio_playback() {
if (stream_id == -1) return;
pthread_mutex_lock(&audio_mutex);
if (!audio_out->state() == QAudio::State::IdleState) {
pthread_mutex_unlock(&audio_mutex);
return;
}
if (parent->pts_start_time < 0.0) {
if (parent->Video.stream_id == -1 && decode_pos > 65) { // start playback
parent->pts_start_time = buffers[0].frame_time;
parent->sys_start_time = (double)parent->timer.elapsed() / 1000.0;
qDebug() << "Audio playback started";
} else {
pthread_mutex_unlock(&audio_mutex);
return;
}
}
if (playback_pos == decode_pos) {
pthread_mutex_unlock(&audio_mutex);
return;
}
AudioBuffer *buffer = nullptr;
double current_sys_time = ((double)parent->timer.elapsed() / 1000.0) - parent->sys_start_time;
bool bounds = false;
int skipped = 0;
while (!bounds) {
if (playback_pos == decode_pos) bounds = true;
else {
AudioBuffer *temp_buffer = &buffers[playback_pos];
double temp_time = temp_buffer->frame_time - parent->pts_start_time;
if (temp_time < current_sys_time ) {
if (buffer) {
buffer->used = false;
skipped++;
}
buffer = temp_buffer;
playback_pos++; playback_pos %= MAX_AUD_BUFFERS;
} else {
bounds = true;
}
}
}
if (skipped > 0) qDebug("Skipped %d audio buffers on playback", skipped);
if (buffer) {
audio_out_device->write((const char *)buffer->data, buffer->buffer_size);
buffer->used = false;
}
pthread_mutex_unlock(&audio_mutex);
}
Qt网站上的例子起初不是那么明显http://qt.apidoc.info/5.1.1/qtmultimedia/audiooutput.html但是当我把它放进去测试时它并不是太糟糕。
答案 1 :(得分:0)
原因是音频数据的来源不是生产质量模块&#34; (它是一个虚拟测试类):计时器正在漂移,因为它的实际间隔是10ms加上处理时间。
其他观察:
QAudioOutput::setBufferSize()
更大QAudioInput::read()
和QAudioOutput::write()
QAudioInput::periodSize()
和QAudioOutput::periodSize()