add test audio input fetch function
This commit is contained in:
parent
cc8e763f97
commit
7dca9255df
@ -55,6 +55,8 @@ local function update_hand()
|
||||
skeleton.set_model("hand", bone, item.model_name(itemid))
|
||||
end
|
||||
|
||||
local stream
|
||||
|
||||
function on_hud_open()
|
||||
input.add_callback("player.pick", function ()
|
||||
if hud.is_paused() or hud.is_inventory_open() then
|
||||
@ -117,16 +119,16 @@ function on_hud_open()
|
||||
|
||||
hud.default_hand_controller = update_hand
|
||||
|
||||
local stream = PCMStream(44100, 1, 8)
|
||||
stream = PCMStream(44100, 1, 16)
|
||||
stream:share("test-stream")
|
||||
local bytes = Bytearray(44100 * 16)
|
||||
local bytes = Bytearray(44100 / 8)
|
||||
for i=1,#bytes do
|
||||
local x = math.sin(i * 0.08) * 127 + 128
|
||||
local x = math.sin(i * 0.08) * 1 + 0
|
||||
bytes[i] = x
|
||||
end
|
||||
stream:feed(bytes)
|
||||
|
||||
audio.play_stream_2d("test-stream", 0.05, 1.0)
|
||||
audio.play_stream_2d("test-stream", 2.0, 1.0, "ui")
|
||||
end
|
||||
|
||||
function on_hud_render()
|
||||
@ -135,4 +137,7 @@ function on_hud_render()
|
||||
else
|
||||
update_hand()
|
||||
end
|
||||
|
||||
local bytes = audio.fetch_input()
|
||||
stream:feed(bytes)
|
||||
end
|
||||
|
||||
@ -5,11 +5,40 @@
|
||||
|
||||
#include "debug/Logger.hpp"
|
||||
#include "alutil.hpp"
|
||||
#include "../MemoryPCMStream.hpp"
|
||||
|
||||
static debug::Logger logger("al-audio");
|
||||
|
||||
using namespace audio;
|
||||
|
||||
const char* alc_error_to_string(ALCenum error) {
|
||||
switch (error) {
|
||||
case ALC_NO_ERROR:
|
||||
return "no error";
|
||||
case ALC_INVALID_DEVICE:
|
||||
return "invalid device handle";
|
||||
case ALC_INVALID_CONTEXT:
|
||||
return "invalid context handle";
|
||||
case ALC_INVALID_ENUM:
|
||||
return "invalid enum parameter passed to an ALC call";
|
||||
case ALC_INVALID_VALUE:
|
||||
return "invalid value parameter passed to an ALC call";
|
||||
case ALC_OUT_OF_MEMORY:
|
||||
return "out of memory";
|
||||
default:
|
||||
return "unknown ALC error";
|
||||
}
|
||||
}
|
||||
|
||||
static void check_alc_errors(ALCdevice* device, const char* context) {
|
||||
ALCenum error = alcGetError(device);
|
||||
if (error == ALC_NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
logger.error() << context << ": " << alc_error_to_string(error) << "("
|
||||
<< error << ")";
|
||||
}
|
||||
|
||||
ALSound::ALSound(
|
||||
ALAudio* al, uint buffer, const std::shared_ptr<PCM>& pcm, bool keepPCM
|
||||
)
|
||||
@ -45,14 +74,17 @@ ALInputDevice::ALInputDevice(
|
||||
|
||||
ALInputDevice::~ALInputDevice() {
|
||||
alcCaptureCloseDevice(device);
|
||||
check_alc_errors(device, "alcCaptureCloseDevice");
|
||||
}
|
||||
|
||||
void ALInputDevice::startCapture() {
|
||||
AL_CHECK(alcCaptureStart(device));
|
||||
alcCaptureStart(device);
|
||||
check_alc_errors(device, "alcCaptureStart");
|
||||
}
|
||||
|
||||
void ALInputDevice::stopCapture() {
|
||||
AL_CHECK(alcCaptureStop(device));
|
||||
alcCaptureStop(device);
|
||||
check_alc_errors(device, "alcCaptureStop");
|
||||
}
|
||||
|
||||
uint ALInputDevice::getChannels() const {
|
||||
@ -60,13 +92,15 @@ uint ALInputDevice::getChannels() const {
|
||||
}
|
||||
|
||||
size_t ALInputDevice::read(char* buffer, size_t bufferSize) {
|
||||
ALCint samplesCount;
|
||||
AL_CHECK(alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, 1, &samplesCount));
|
||||
ALCint samplesCount = 0;
|
||||
alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, sizeof(samplesCount), &samplesCount);
|
||||
check_alc_errors(device, "alcGetIntegerv(ALC_CAPTURE_SAMPLES)");
|
||||
size_t samplesRead = std::min<ALCsizei>(
|
||||
samplesCount, bufferSize / channels / (bitsPerSample >> 3)
|
||||
);
|
||||
AL_CHECK(alcCaptureSamples(device, buffer, samplesRead));
|
||||
return samplesRead;
|
||||
alcCaptureSamples(device, buffer, samplesRead);
|
||||
check_alc_errors(device, "alcCaptureSamples");
|
||||
return samplesRead * channels * (bitsPerSample >> 3);
|
||||
}
|
||||
|
||||
ALStream::ALStream(
|
||||
@ -195,7 +229,7 @@ void ALStream::update(double delta) {
|
||||
|
||||
// alspeaker->stopped is assigned to false at ALSpeaker::play(...)
|
||||
if (p_speaker->isStopped() && !alspeaker->stopped) { //TODO: -V560 false-positive?
|
||||
if (preloaded) {
|
||||
if (preloaded || dynamic_cast<MemoryPCMStream*>(source.get())) {
|
||||
p_speaker->play();
|
||||
} else {
|
||||
p_speaker->stop();
|
||||
@ -417,8 +451,10 @@ ALAudio::~ALAudio() {
|
||||
AL_CHECK(alDeleteBuffers(1, &buffer));
|
||||
}
|
||||
|
||||
AL_CHECK(alcMakeContextCurrent(context));
|
||||
alcMakeContextCurrent(nullptr);
|
||||
check_alc_errors(device, "alcMakeContextCurrent");
|
||||
alcDestroyContext(context);
|
||||
check_alc_errors(device, "alcDestroyContext");
|
||||
if (!alcCloseDevice(device)) {
|
||||
logger.error() << "device not closed!";
|
||||
}
|
||||
@ -447,15 +483,16 @@ std::unique_ptr<InputDevice> ALAudio::openInputDevice(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
) {
|
||||
uint bps = bitsPerSample >> 3;
|
||||
AL_CHECK(
|
||||
ALCdevice* device = alcCaptureOpenDevice(
|
||||
nullptr,
|
||||
sampleRate,
|
||||
AL::to_al_format(channels, bps),
|
||||
sampleRate * channels * bps
|
||||
)
|
||||
ALCdevice* device = alcCaptureOpenDevice(
|
||||
nullptr,
|
||||
sampleRate,
|
||||
AL::to_al_format(channels, bitsPerSample),
|
||||
sampleRate * channels * bps / 8
|
||||
);
|
||||
check_alc_errors(device, "alcCaptureOpenDevice");
|
||||
return std::make_unique<ALInputDevice>(
|
||||
this, device, channels, bitsPerSample
|
||||
);
|
||||
return std::make_unique<ALInputDevice>(this, device, channels, bps);
|
||||
}
|
||||
|
||||
std::unique_ptr<ALAudio> ALAudio::create() {
|
||||
|
||||
@ -151,6 +151,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static std::unique_ptr<InputDevice> input_device = nullptr;
|
||||
|
||||
void audio::initialize(bool enabled, AudioSettings& settings) {
|
||||
enabled = enabled && settings.enabled.get();
|
||||
if (enabled) {
|
||||
@ -180,6 +182,13 @@ void audio::initialize(bool enabled, AudioSettings& settings) {
|
||||
audio::get_channel(channel.name)->setVolume(value * value);
|
||||
}, true));
|
||||
}
|
||||
|
||||
input_device = backend->openInputDevice(44100, 1, 16);
|
||||
input_device->startCapture();
|
||||
}
|
||||
|
||||
InputDevice* audio::get_input_device() {
|
||||
return input_device.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<PCM> audio::load_PCM(const io::path& file, bool headerOnly) {
|
||||
@ -458,6 +467,7 @@ void audio::reset_channel(int index) {
|
||||
}
|
||||
|
||||
void audio::close() {
|
||||
input_device->stopCapture();
|
||||
speakers.clear();
|
||||
delete backend;
|
||||
backend = nullptr;
|
||||
|
||||
@ -24,6 +24,8 @@ namespace audio {
|
||||
/// @brief streams and important sounds
|
||||
constexpr inline int PRIORITY_HIGH = 10;
|
||||
|
||||
constexpr inline size_t MAX_INPUT_SAMPLES = 22050;
|
||||
|
||||
class Speaker;
|
||||
|
||||
/// @brief Audio speaker states
|
||||
@ -423,6 +425,15 @@ namespace audio {
|
||||
std::shared_ptr<PCMStream> stream, bool keepSource
|
||||
);
|
||||
|
||||
/// @brief Open audio input device
|
||||
/// @param sampleRate sample rate
|
||||
/// @param channels channels count (1 - mono, 2 - stereo)
|
||||
/// @param bitsPerSample number of bits per sample (8 or 16)
|
||||
/// @return new InputDevice instance or nullptr
|
||||
std::unique_ptr<InputDevice> open_input_device(
|
||||
uint sampleRate, uint channels, uint bitsPerSample
|
||||
);
|
||||
|
||||
/// @brief Configure 3D listener
|
||||
/// @param position listener position
|
||||
/// @param velocity listener velocity (used for Doppler effect)
|
||||
@ -536,6 +547,8 @@ namespace audio {
|
||||
/// @brief Stop all playing audio in channel, reset channel state
|
||||
void reset_channel(int channel);
|
||||
|
||||
InputDevice* get_input_device();
|
||||
|
||||
/// @brief Finalize audio system
|
||||
void close();
|
||||
};
|
||||
|
||||
@ -379,16 +379,35 @@ static int l_audio_get_velocity(lua::State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// @brief audio.count_speakers() -> integer
|
||||
/// @brief audio.count_speakers() -> integer
|
||||
static int l_audio_count_speakers(lua::State* L) {
|
||||
return lua::pushinteger(L, audio::count_speakers());
|
||||
}
|
||||
|
||||
// @brief audio.count_streams() -> integer
|
||||
/// @brief audio.count_streams() -> integer
|
||||
static int l_audio_count_streams(lua::State* L) {
|
||||
return lua::pushinteger(L, audio::count_streams());
|
||||
}
|
||||
|
||||
/// @brief audio.fetch_input(size) -> Bytearray
|
||||
static int l_audio_fetch_input(lua::State* L) {
|
||||
auto device = audio::get_input_device();
|
||||
if (device == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
size_t size = lua::touinteger(L, 1);
|
||||
const size_t MAX_BUFFER_SIZE = audio::MAX_INPUT_SAMPLES * 4;
|
||||
if (size == 0) {
|
||||
size = MAX_BUFFER_SIZE;
|
||||
}
|
||||
size = std::min<size_t>(size, MAX_BUFFER_SIZE);
|
||||
ubyte buffer[MAX_BUFFER_SIZE];
|
||||
size = device->read(reinterpret_cast<char*>(buffer), size);
|
||||
|
||||
std::vector<ubyte> bytes(buffer, buffer + size);
|
||||
return lua::create_bytearray(L, std::move(bytes));
|
||||
}
|
||||
|
||||
const luaL_Reg audiolib[] = {
|
||||
{"play_sound", lua::wrap<l_audio_play_sound>},
|
||||
{"play_sound_2d", lua::wrap<l_audio_play_sound_2d>},
|
||||
@ -414,5 +433,6 @@ const luaL_Reg audiolib[] = {
|
||||
{"get_velocity", lua::wrap<l_audio_get_velocity>},
|
||||
{"count_speakers", lua::wrap<l_audio_count_speakers>},
|
||||
{"count_streams", lua::wrap<l_audio_count_streams>},
|
||||
{"fetch_input", lua::wrap<l_audio_fetch_input>},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
@ -18,10 +18,7 @@ const std::shared_ptr<audio::MemoryPCMStream>& LuaPCMStream::getStream() const {
|
||||
return stream;
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
|
||||
static int l_feed(lua::State* L) {
|
||||
std::cout << "feed" << std::endl;
|
||||
auto stream = touserdata<LuaPCMStream>(L, 1);
|
||||
if (stream == nullptr) {
|
||||
return 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user