Skip to content

Commit

Permalink
miniaudio: finish implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jcelerier committed Dec 27, 2024
1 parent 1dfa430 commit 9035a3a
Showing 1 changed file with 81 additions and 21 deletions.
102 changes: 81 additions & 21 deletions src/ossia/audio/miniaudio_protocol.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#pragma once
#include <ossia/detail/config.hpp>

//#if 1 || defined(OSSIA_ENABLE_MINIAUDIO)
#if __has_include(<miniaudio.h>)
#define OSSIA_ENABLE_MINIAUDIO 1
#define MINIAUDIO_IMPLEMENTATION
#if defined(__APPLE__)
#define MA_NO_RUNTIME_LINKING 1
Expand All @@ -16,32 +17,74 @@
#define MA_NO_NODE_GRAPH 1
#define MA_NO_GENERATION 1
#define MA_API
#if __has_include(<miniaudio.h>)

#include <ossia/audio/audio_engine.hpp>
#include <ossia/detail/thread.hpp>

#include <miniaudio.h>
#include <kfr/base/conversion.hpp>

#include <iostream>
#include <miniaudio.h>

#define OSSIA_AUDIO_MINIAUDIO 1

namespace ossia
{
struct miniaudio_context
{
ma_context context;
};

class miniaudio_engine final : public audio_engine
{

public:
std::vector<const ma_device_info*> devices;
bool is_duplex(const ma_device_id& card_in, const ma_device_id& card_out)
{
#if defined(__APPLE__)
return true;
std::string_view i = card_in.coreaudio;
std::string_view o = card_out.coreaudio;
if(i.length() != o.length() || i.empty() || o.empty())
return false;
if(i.substr(0, i.size() - 1) == o.substr(0, o.size() - 1))
return true;

#endif
return memcmp(&card_in, &card_out, sizeof(ma_device_id)) == 0;
}
miniaudio_engine(
std::string name, std::string card_in, std::string card_out, int inputs,
int outputs, int rate, int bs)
std::shared_ptr<miniaudio_context> ctx, std::string name,
const ma_device_id& card_in, const ma_device_id& card_out, int inputs, int outputs,
int rate, int bs)
: m_ctx{std::move(ctx)}
{
ma_device_config config = ma_device_config_init(ma_device_type_duplex);
ma_device_type dtype = ma_device_type_duplex;
if(inputs == 0)
dtype = ma_device_type_playback;
else if(outputs == 0)
dtype = ma_device_type_capture;

ma_device_config config = ma_device_config_init(dtype);

config.sampleRate = rate;
config.periodSizeInFrames = bs;
config.playback.channels = outputs;
config.playback.format = ma_format_f32;
config.capture.channels = inputs;
config.capture.format = ma_format_f32;

if(outputs > 0)
{
config.playback.pDeviceID = &card_out;
config.playback.channels = outputs;
config.playback.format = ma_format_f32;
// config.playback.shareMode = ma_share_mode_exclusive;
}

if(inputs > 0)
{
config.capture.pDeviceID = &card_in;
config.capture.channels = inputs;
config.capture.format = ma_format_f32;
// config.capture.shareMode = ma_share_mode_exclusive;
}

config.dataCallback = callback;

Expand All @@ -50,11 +93,19 @@ class miniaudio_engine final : public audio_engine
config.noClip = false;
config.noDisableDenormals = false;
config.noPreSilencedOutputBuffer = false;

config.pUserData = this;

if(ma_device_init(NULL, &config, &m_stream) != MA_SUCCESS)
if(ma_device_init(&m_ctx->context, &config, &m_stream) != MA_SUCCESS)
throw std::runtime_error("Cannot initialize miniaudio");
ma_device_start(&m_stream);

if(ma_device_start(&m_stream) != MA_SUCCESS)
throw std::runtime_error("Cannot start miniaudio");

this->effective_buffer_size = bs;
this->effective_sample_rate = rate;
this->effective_inputs = inputs;
this->effective_outputs = outputs;
}

bool running() const override
Expand Down Expand Up @@ -91,20 +142,29 @@ class miniaudio_engine final : public audio_engine
return;
}

auto float_input = ((float* const*)input);
auto float_output = ((float**)output);
float ins_data[self.effective_inputs * nframes];
float* ins[self.effective_inputs + 2];
for(int i = 0; i < self.effective_inputs; i++)
ins[i] = ins_data + i * nframes;
kfr::deinterleave(ins, (float*)input, self.effective_inputs, nframes);

float outs_data[self.effective_outputs * nframes];
std::memset(outs_data, 0, sizeof(float) * self.effective_outputs * nframes);
float* outs[self.effective_outputs + 2];
for(int i = 0; i < self.effective_outputs; i++)
outs[i] = outs_data + i * nframes;

ossia::audio_tick_state ts{float_input,
float_output,
self.effective_inputs,
self.effective_outputs,
nframes,
0};
ossia::audio_tick_state ts{(float* const*)ins, outs, self.effective_inputs,
self.effective_outputs, nframes, 0}; //FIXME timing
self.audio_tick(ts);

self.tick_end();

kfr::interleave(
(float*)output, (const float**)outs, self.effective_outputs, nframes);
}

std::shared_ptr<miniaudio_context> m_ctx;
ma_device m_stream;
};
}
Expand Down

0 comments on commit 9035a3a

Please sign in to comment.