我是 c++ 的新手,必须为 uni 做一个练习。将实施一个抖动缓冲器(FIFO 缓冲器)来缓冲所需数量的音频数据包,直到它们被音频进程读取为止。理想情况下,允许在操作期间可变地设置 1 到 50 之间的缓冲区大小的实现。 当我尝试编译我的代码时出现此错误,有人可以帮忙吗?
main.cpp:
//main.cpp
#include <QApplication>
#include "ias.h"
#include "udp_receiver.h"
#include "udp_transmitter.h"
#include <thread>
#include <sys/socket.h>
int main(int argc, char *argv[]){
QApplication yo(argc,argv);
int socket = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int port = 5401;
sockaddr_in address_in;
address_in.sin_family = AF_INET;
address_in.sin_addr.s_addr = inet_addr("144.76.81.210");
//address_in.sin_addr.s_addr = inet_addr("127.0.0.1");
address_in.sin_port = htons(port);
int binding = ::bind(socket, reinterpret_cast<sockaddr*>(&address_in), sizeof(address_in));
if (binding < 0)
cout << "Socket could not bind. Errorcode: " << binding << endl;
udp_transmitter transmitter(socket, address_in);
udp_receiver receiver(socket);
std::thread t(&udp_receiver::receive,&receiver);
ias myIAS(&transmitter, &receiver);
std::thread t1(&udp_receiver::changeMaxSize,&receiver);
return yo.exec();
/*std::thread t(&udp_receiver::receiveA,&receiver);
return transmitter.executeA();*/
}
这是ias.cpp:
//ias.cpp
#include "ias.h"
static int portAudioCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *data ){
(void) framesPerBuffer;
(void) timeInfo;
(void) statusFlags;
ias::callbackdata *my;
my = (ias::callbackdata *) data;
int maxFrameSize = 6*framesPerBuffer;
/// INPUT UND OUTPUT BUFFER DEFINIEREN
unsigned char *input = (unsigned char*) inputBuffer;
unsigned char *output = (unsigned char*) outputBuffer;
///ENCODING
unsigned char cbits[maxFrameSize];
opus_int16 in[(int)framesPerBuffer];
//little endian conversion (smallest end is saved first)
for(int i=0; i < (int)framesPerBuffer; i++){
in[i]=input[2*i+1]<<8|input[2*i];
}
opus_int32 compressedBytes = opus_custom_encode(my->enc,in,my->frameSize,cbits,maxFrameSize);
/// RECHTECK GENERATOR
for (int i=0; i<(int)framesPerBuffer*2;i++){
// if (my->even == true) output[i] = 244; else output[i] = 0;
}
/// EVEN / ODD VERÄNDERN
if (my->even == true) my->even = false; else my->even = true;
///SEND UDP
my->udp_transmitter->execute(cbits);
/// RECEIVE UDP
if (my->udp_receiver->packetAvailable()) {
unsigned char* received = my->udp_receiver->getNextPacket();
///OUTPUT DECODED STREAM
opus_int16 out[maxFrameSize];
opus_int32 decompressedBytes = opus_custom_decode(my->dec,received,compressedBytes,out,maxFrameSize);
if (decompressedBytes < 0) cout << "decompression failed" << endl;
for(int i=0; i < decompressedBytes; i++) {
output[2*i]=out[i]&0xFF;
output[2*i+1]=(out[i]>>8)&0xFF;
}
/*for (int i=0; i<(int)framesPerBuffer*2;i++){
output[i] = received[i];
}*/
my->udp_receiver->removeNextPacket();
}
return 0;
}
/// CONSTRUCTOR
ias::ias(udp_transmitter* transmitter, udp_receiver* receiver){
/// SPEICHER FÜR CALLBACK-DATA STRUCT RESERVIEREN
dFC = new callbackdata();
dFC->even = false;
dFC->udp_receiver = receiver;
dFC->udp_transmitter = transmitter;
dFC->myIAS = this;
/// PORTAUDIO INITIALISIEREN
paErr = Pa_Initialize();
if (paErr == paNoError){
amountOfAudioDevices = -1;
amountOfAudioDevices = Pa_GetDeviceCount();
if( amountOfAudioDevices < 0 ){
cout << "ERROR: CountDevices returned:" << amountOfAudioDevices << endl;
}
}
/// INFO ZU VORHANDENEN AUDIODEVICES AUSGEBEN
for (int i=0;i<=amountOfAudioDevices-1;i++) {
info = Pa_GetDeviceInfo(i);
cout << "device = " << i << endl;
cout << "name = " << info->name << endl;
cout << "maximum output channels = " << info->maxOutputChannels << endl;
cout << "maximum input channels = " << info->maxInputChannels << endl;
cout << "default sample rate = " << info->defaultSampleRate << endl;
cout << endl;
}
/// PARAMETER FESTLEGEN
audiofault = false;
soundIsRunning = false;
frameSize = 512;
dFC->frameSize = frameSize;
sampleRate = 48000;
audioChannels = 1;
/// AUDIODEVICE KONFIGURIEREN
PaStreamParameters outputParameters;
PaStreamParameters inputParameters;
bzero( &inputParameters, sizeof( inputParameters ) );
inputParameters.channelCount = audioChannels;
inputParameters.device = 2;//4;//3;//0
inputParameters.sampleFormat = paInt16;
inputParameters.hostApiSpecificStreamInfo = NULL;
#ifdef __MACOSX_CORE__
static PaMacCoreStreamInfo coreAudioInputInfo;
PaMacCore_SetupStreamInfo(&coreAudioInputInfo, paMacCorePro);
inputParameters.hostApiSpecificStreamInfo = &coreAudioInputInfo;
#endif
bzero( &outputParameters, sizeof( outputParameters ) );
outputParameters.channelCount = audioChannels;
outputParameters.device = 1;//2;//1
outputParameters.sampleFormat = paInt16;
outputParameters.hostApiSpecificStreamInfo = NULL;
#ifdef __MACOSX_CORE__
static PaMacCoreStreamInfo coreAudioOutputInfo;
PaMacCore_SetupStreamInfo(&coreAudioOutputInfo, paMacCorePro);
outputParameters.hostApiSpecificStreamInfo = &coreAudioOutputInfo;
#endif
inputParameters.suggestedLatency = 0.001;
outputParameters.suggestedLatency = 0.001;
paErr = Pa_OpenStream( &stream,
&inputParameters,
&outputParameters,
sampleRate,
frameSize,
paClipOff,
portAudioCallback,
dFC);
if (paErr==paNoError) audiofault = false; else audiofault = true;
/// AUDIODEVICE STARTEN
if (!audiofault){
#ifdef __LINUX_ALSA__
PaAlsa_EnableRealtimeScheduling(stream,true);
#endif
paErr = Pa_StartStream(stream);
if (paErr==paNoError){
soundIsRunning = true;
cout << "SOUND IS RUNNING" << endl;
}
else{
soundIsRunning = false;
cout << "SOUND IS NOT RUNNING" << endl;
}
} else{
soundIsRunning = false;
cout << "SOUND IS NOT RUNNING" << endl;
}
/// OPUS SPECIFICS
int err;
opusMode = opus_custom_mode_create(sampleRate, frameSize, &err);
if (err != OPUS_OK) {
cout << "Cannot create Opus Moude - Error: " << opus_strerror(err) << endl;
exit(EXIT_FAILURE);
}
enc = opus_custom_encoder_create(opusMode, audioChannels, &err);
if (err != OPUS_OK) {
cout << "Cannot create encoder: " << opus_strerror(err) << endl;
exit(EXIT_FAILURE);
}
dFC->enc = enc;
dec = opus_custom_decoder_create(opusMode, audioChannels, &err);
if (err != OPUS_OK) {
cout << "Cannot create decoder: " << opus_strerror(err) << endl;
exit(EXIT_FAILURE);
}
dFC->dec = dec;
}
ias::~ias(){
cout << "Program is destructed now ..." << endl;
if (soundIsRunning){
paErr = Pa_CloseStream( stream );
if (paErr == 0){
soundIsRunning = false;
}
}
}
#ifdef WIN32
int ias::gettimeofday(struct timeval *tv, struct timezone *tz){
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv){
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
/*converting file time to unix epoch*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tmpres /= 10; /*convert into microseconds*/
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz){
if (!tzflag){
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
#endif
这是 ias.h
//ias.h
#ifndef H_IAS_
#define H_IAS_
#include <QWidget>
#include "udp_receiver.h"
#include "udp_transmitter.h"
#include <unistd.h>
// std-includes
#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <cstdio>
#include <math.h>
#include <sys/time.h>
/// OPUS INCLUDES
#include <opus.h>
#include <opus_custom.h>
#include <opus_types.h>
// AV
#include "./include/portaudio/include/portaudio.h"
#ifdef WIN32
#include <winsock2.h>
#endif
#ifdef WIN32
#include <windows.h>
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 116444736000000000Ui64 //11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 116444736000000000ULL //11644473600000000ULL
#endif
#endif
#ifdef __MACOSX_CORE__
#include "./include/portaudio/include/pa_mac_core.h"
#endif
#ifdef __LINUX_ALSA__
#include "./include/portaudio/include/pa_linux_alsa.h"
#endif
#define bzero(b,len) (memset((b),'\0',(len)), (void)0)
using namespace std;
class ias : public QWidget{
Q_OBJECT
public :
ias(udp_transmitter* transmitter, udp_receiver* receiver);
~ias();
// AUDIO
PaStream *stream;
PaError paErr;
const PaDeviceInfo *info;
bool audiofault;
bool soundIsRunning;
// SOUND SPECIFIC VARIABLES
int amountOfAudioDevices,
inputDevice,
outputDevice,
format,
audioChannels,
sampleRate,
frameSize;
// OPUS SPECIFIC VARIABLES
opus_int16 *shortBuffer, *channel1Short, *channel2Short;
OpusCustomEncoder *enc, *enc2;
OpusCustomDecoder *dec;
OpusCustomMode *opusMode;
unsigned char *celtDone, *channel1Done;
// CALLBACK
struct callbackdata{
ias *myIAS;
double callbackInterval;
double before;
double after;
bool even;
udp_transmitter* udp_transmitter;
udp_receiver* udp_receiver;
OpusCustomEncoder *enc;
OpusCustomDecoder *dec;
int frameSize;
};
callbackdata *dFC;
#ifdef WIN32
int gettimeofday(struct timeval *tv, struct timezone *tz);
#endif
private:
public slots:
private slots:
};
#endif
这是udp_receiver.h:
//udp_receiver.h
#ifndef UDP_RECEIVER_H
#define UDP_RECEIVER_H
#include <iostream>
#include <string>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include "./include/portaudio/include/portaudio.h"
#include <vector>
using namespace std;
class udp_receiver {
private:
int socket;
struct Packet {
unsigned char msg[960];
};
static vector<Packet> jitterBuffer;
public:
udp_receiver(int socket);
~udp_receiver();
void receiveA();
void receive();
bool packetAvailable();
unsigned char* getNextPacket();
void removeNextPacket();
void changeMaxSize();
Packet* lastReceived;
unsigned long jitterBufferMaxSize;
};
#endif
//udp_transmitter.h
#ifndef UDP_TRANSMITTER_H
#define UDP_TRANSMITTER_H
#include <iostream>
#include <string>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <chrono>
#include <thread>
#include "./include/portaudio/include/portaudio.h"
using namespace std;
class udp_transmitter {
private:
int socket;
sockaddr_in destination;
public:
udp_transmitter(int socket, sockaddr_in destination);
~udp_transmitter();
int executeA();
int execute(unsigned char *input);
};
#endif