... because we switched to unmodified oboe. The wrapper is built as separate local vcpkg port that depends on oboe. Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
		
			
				
	
	
		
			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);
 | 
						|
    }
 | 
						|
} |