1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Audio call reception

Can hear, but can't talk

Uses a hardwired tox_do() interval of 50ms until to_do_interval() gets fixed
This commit is contained in:
Tux3 / Mlkj / !Lev.uXFMLA 2014-06-27 18:51:08 +02:00
parent 749f4c9ed7
commit f5a628fafb
5 changed files with 94 additions and 19 deletions

36
audiobuffer.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "audiobuffer.h"
AudioBuffer::AudioBuffer() :
QIODevice(0)
{
open(QIODevice::ReadOnly);
}
AudioBuffer::~AudioBuffer()
{
close();
}
qint64 AudioBuffer::readData(char *data, qint64 len)
{
const qint64 total = qMin((qint64)buffer.size(), len);
memcpy(data, buffer.constData(), total);
buffer = buffer.mid(total);
return total;
}
qint64 AudioBuffer::writeData(const char* data, qint64 len)
{
buffer.append(data, len);
return 0;
}
qint64 AudioBuffer::bytesAvailable() const
{
return buffer.size() + QIODevice::bytesAvailable();
}
qint64 AudioBuffer::bufferSize() const
{
return buffer.size();
}

23
audiobuffer.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef AUDIOBUFFER_H
#define AUDIOBUFFER_H
#include <QIODevice>
#include <QByteArray>
class AudioBuffer : public QIODevice
{
Q_OBJECT
public:
explicit AudioBuffer();
~AudioBuffer();
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
qint64 bytesAvailable() const;
qint64 bufferSize() const;
private:
QByteArray buffer;
};
#endif // AUDIOBUFFER_H

View File

@ -17,6 +17,7 @@
#include "core.h" #include "core.h"
#include "cdata.h" #include "cdata.h"
#include "cstring.h" #include "cstring.h"
#include "settings.h"
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
@ -27,8 +28,6 @@
#include <QThread> #include <QThread>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include "settings.h"
const QString Core::CONFIG_FILE_NAME = "tox_save"; const QString Core::CONFIG_FILE_NAME = "tox_save";
QList<ToxFile> Core::fileSendQueue; QList<ToxFile> Core::fileSendQueue;
QList<ToxFile> Core::fileRecvQueue; QList<ToxFile> Core::fileRecvQueue;
@ -623,7 +622,9 @@ void Core::process()
fflush(stdout); fflush(stdout);
#endif #endif
checkConnection(); checkConnection();
toxTimer->start(tox_do_interval(tox)); int toxInterval = tox_do_interval(tox);
//qDebug() << QString("Tox interval %1").arg(toxInterval);
toxTimer->start(50);
} }
void Core::checkConnection() void Core::checkConnection()
@ -1027,7 +1028,6 @@ void Core::prepareCall(int friendId, int callId, ToxAv* toxav)
qDebug() << QString("Core: preparing call %1").arg(callId); qDebug() << QString("Core: preparing call %1").arg(callId);
calls[callId].callId = callId; calls[callId].callId = callId;
calls[callId].friendId = friendId; calls[callId].friendId = friendId;
calls[callId].audioBuffer.open(QBuffer::ReadWrite);
calls[callId].codecSettings = av_DefaultSettings; calls[callId].codecSettings = av_DefaultSettings;
toxav_prepare_transmission(toxav, callId, &calls[callId].codecSettings, false); toxav_prepare_transmission(toxav, callId, &calls[callId].codecSettings, false);
QAudioFormat format; QAudioFormat format;
@ -1047,11 +1047,16 @@ void Core::prepareCall(int friendId, int callId, ToxAv* toxav)
calls[callId].audioOutput = new QAudioOutput(format); calls[callId].audioOutput = new QAudioOutput(format);
calls[callId].active = true; calls[callId].active = true;
QtConcurrent::run(playCallAudio, callId, toxav); calls[callId].audioOutput->setBufferSize(24000);
calls[callId].audioOutput->start(&calls[callId].audioBuffer); calls[callId].audioOutput->start(&calls[callId].audioBuffer);
if (calls[callId].audioOutput->state() == QAudio::StoppedState if (calls[callId].audioOutput->state() == QAudio::StoppedState
&& calls[callId].audioOutput->error() == QAudio::OpenError) && calls[callId].audioOutput->error() == QAudio::OpenError)
{
qWarning() << "Core: Unable to start audio"; qWarning() << "Core: Unable to start audio";
}
else
qDebug() << QString("Core: Audio started, buffer size %1").arg(calls[callId].audioOutput->bufferSize());
QtConcurrent::run(playCallAudio, callId, toxav);
} }
void Core::cleanupCall(int callId) void Core::cleanupCall(int callId)
@ -1062,7 +1067,6 @@ void Core::cleanupCall(int callId)
{ {
delete calls[callId].audioOutput; delete calls[callId].audioOutput;
} }
calls[callId].audioBuffer.close();
} }
void Core::playCallAudio(int callId, ToxAv* toxav) void Core::playCallAudio(int callId, ToxAv* toxav)
@ -1070,25 +1074,34 @@ void Core::playCallAudio(int callId, ToxAv* toxav)
while (calls[callId].active) while (calls[callId].active)
{ {
int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000; int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000;
int16_t buf[framesize]; uint8_t buf[framesize*2];
int len = toxav_recv_audio(toxav, callId, framesize, buf); int len = toxav_recv_audio(toxav, callId, framesize, (int16_t*)buf);
qDebug() << QString("Core: Received %1 audio bytes").arg(len);
if (len < 0) if (len < 0)
{ {
qDebug() << "Core::playCallAudio: Error receiving audio"; qDebug() << QString("Core::playCallAudio: Error receiving audio: %1").arg(len);
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2); QThread::msleep(5);
continue; continue;
} }
if (len == 0) if (len == 0)
{
qApp->processEvents();
QThread::msleep(5);
continue; continue;
qDebug() << QString("Core::playCallAudio: Playing %1 frames/sample").arg(len); }
calls[callId].audioBuffer.write((char*)buf, len*2); //qDebug() << QString("Core: Received %1 bytes, %2 audio bytes free, %3 core buffer size")
calls[callId].audioBuffer.seek(0); //.arg(len*2).arg(calls[callId].audioOutput->bytesFree()).arg(calls[callId].audioBuffer.bufferSize());
calls[callId].audioOutput->resume(); calls[callId].audioBuffer.writeData((char*)buf, len*2);
int state = calls[callId].audioOutput->state();
if (state != QAudio::ActiveState)
{
qDebug() << QString("Core: Audio state is %1").arg(state);
}
int error = calls[callId].audioOutput->error(); int error = calls[callId].audioOutput->error();
if (error != QAudio::NoError) if (error != QAudio::NoError)
qWarning() << QString("Core::playCallAudio: Error: %1").arg(error); qWarning() << QString("Core::playCallAudio: Error: %1").arg(error);
QThread::msleep(calls[callId].codecSettings.audio_frame_duration / 2); QThread::msleep(5);
} }
} }

5
core.h
View File

@ -18,6 +18,7 @@
#define CORE_HPP #define CORE_HPP
#include "status.h" #include "status.h"
#include "audiobuffer.h"
#include <tox/tox.h> #include <tox/tox.h>
#include <tox/toxav.h> #include <tox/toxav.h>
@ -33,7 +34,7 @@
#include <QBuffer> #include <QBuffer>
#include <QAudioOutput> #include <QAudioOutput>
#define TOXAV_MAX_CALLS 32 #define TOXAV_MAX_CALLS 16
#define GROUPCHAT_MAX_SIZE 32 #define GROUPCHAT_MAX_SIZE 32
#define TOX_SAVE_INTERVAL 30*1000 #define TOX_SAVE_INTERVAL 30*1000
#define TOX_FILE_INTERVAL 20 #define TOX_FILE_INTERVAL 20
@ -82,7 +83,7 @@ struct ToxFile
struct ToxCall struct ToxCall
{ {
public: public:
QBuffer audioBuffer; AudioBuffer audioBuffer;
QAudioOutput* audioOutput; QAudioOutput* audioOutput;
ToxAvCodecSettings codecSettings; ToxAvCodecSettings codecSettings;
int callId; int callId;

View File

@ -33,7 +33,8 @@ HEADERS += widget/form/addfriendform.h \
core.h \ core.h \
friendlist.h \ friendlist.h \
cdata.h \ cdata.h \
cstring.h cstring.h \
audiobuffer.h
FORMS += widget.ui FORMS += widget.ui
@ -68,4 +69,5 @@ SOURCES += \
settings.cpp \ settings.cpp \
status.cpp \ status.cpp \
cdata.cpp \ cdata.cpp \
cstring.cpp cstring.cpp \
audiobuffer.cpp