mirror of
https://github.com/rustdesk/rustdesk.git
synced 2024-12-15 03:59:04 +08:00
118 lines
2.7 KiB
C++
118 lines
2.7 KiB
C++
|
#include <oboe/Oboe.h>
|
||
|
#include <math.h>
|
||
|
#include <deque>
|
||
|
#include <pthread.h>
|
||
|
|
||
|
// I got link problem with std::mutex, so use pthread instead
|
||
|
class CThreadLock
|
||
|
{
|
||
|
public:
|
||
|
CThreadLock();
|
||
|
virtual ~CThreadLock();
|
||
|
|
||
|
void Lock();
|
||
|
void Unlock();
|
||
|
|
||
|
private:
|
||
|
pthread_mutex_t mutexlock;
|
||
|
};
|
||
|
|
||
|
CThreadLock::CThreadLock()
|
||
|
{
|
||
|
// init lock here
|
||
|
pthread_mutex_init(&mutexlock, 0);
|
||
|
}
|
||
|
|
||
|
CThreadLock::~CThreadLock()
|
||
|
{
|
||
|
// deinit lock here
|
||
|
pthread_mutex_destroy(&mutexlock);
|
||
|
}
|
||
|
void CThreadLock::Lock()
|
||
|
{
|
||
|
// lock
|
||
|
pthread_mutex_lock(&mutexlock);
|
||
|
}
|
||
|
void CThreadLock::Unlock()
|
||
|
{
|
||
|
// unlock
|
||
|
pthread_mutex_unlock(&mutexlock);
|
||
|
}
|
||
|
|
||
|
class Player : public oboe::AudioStreamDataCallback
|
||
|
{
|
||
|
public:
|
||
|
Player(int channels, int sample_rate)
|
||
|
{
|
||
|
this->channels = channels;
|
||
|
oboe::AudioStreamBuilder builder;
|
||
|
// The builder set methods can be chained for convenience.
|
||
|
builder.setSharingMode(oboe::SharingMode::Exclusive)
|
||
|
->setPerformanceMode(oboe::PerformanceMode::LowLatency)
|
||
|
->setChannelCount(channels)
|
||
|
->setSampleRate(sample_rate)
|
||
|
->setFormat(oboe::AudioFormat::Float)
|
||
|
->setDataCallback(this)
|
||
|
->openManagedStream(outStream);
|
||
|
// Typically, start the stream after querying some stream information, as well as some input from the user
|
||
|
outStream->requestStart();
|
||
|
}
|
||
|
|
||
|
~Player() {
|
||
|
outStream->requestStop();
|
||
|
}
|
||
|
|
||
|
oboe::DataCallbackResult onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) override
|
||
|
{
|
||
|
float *floatData = (float *)audioData;
|
||
|
int i = 0;
|
||
|
mtx.Lock();
|
||
|
auto n = channels * numFrames;
|
||
|
for (; i < n && i < (int)buffer.size(); ++i, ++floatData)
|
||
|
{
|
||
|
*floatData = buffer.front();
|
||
|
buffer.pop_front();
|
||
|
}
|
||
|
mtx.Unlock();
|
||
|
for (; i < n; ++i, ++floatData)
|
||
|
{
|
||
|
*floatData = 0;
|
||
|
}
|
||
|
return oboe::DataCallbackResult::Continue;
|
||
|
}
|
||
|
|
||
|
void push(const float *v, int n)
|
||
|
{
|
||
|
mtx.Lock();
|
||
|
for (auto i = 0; i < n; ++i, ++v)
|
||
|
buffer.push_back(*v);
|
||
|
// in case memory overuse
|
||
|
if (buffer.size() > 48 * 1024 * 120)
|
||
|
buffer.clear();
|
||
|
mtx.Unlock();
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
oboe::ManagedStream outStream;
|
||
|
int channels;
|
||
|
std::deque<float> buffer;
|
||
|
CThreadLock mtx;
|
||
|
};
|
||
|
|
||
|
extern "C"
|
||
|
{
|
||
|
void *create_oboe_player(int channels, int sample_rate)
|
||
|
{
|
||
|
return new Player(channels, sample_rate);
|
||
|
}
|
||
|
|
||
|
void push_oboe_data(void *player, const float* v, int n)
|
||
|
{
|
||
|
static_cast<Player *>(player)->push(v, n);
|
||
|
}
|
||
|
|
||
|
void destroy_oboe_player(void *player)
|
||
|
{
|
||
|
delete static_cast<Player *>(player);
|
||
|
}
|
||
|
}
|