Skip to content

Commit

Permalink
miniaudio fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
stakira committed Jul 28, 2024
1 parent 41f198b commit 6958d68
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 26 deletions.
28 changes: 15 additions & 13 deletions OpenUtau.Core/Audio/MiniAudioOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using NAudio.Wave;
using NAudio.Wave.SampleProviders;
using OpenUtau.Core.Util;
using Serilog;

namespace OpenUtau.Audio {
public class MiniAudioOutput : IAudioOutput, IDisposable {
Expand Down Expand Up @@ -40,28 +41,29 @@ public MiniAudioOutput() {
private void UpdateDeviceList() {
devices.Clear();
unsafe {
ou_audio_device_info_t* device_infos = stackalloc ou_audio_device_info_t[16];
int count = ou_get_audio_device_infos(device_infos, 16);
const int kMaxCount = 128;
ou_audio_device_info_t* device_infos = stackalloc ou_audio_device_info_t[kMaxCount];
int count = ou_get_audio_device_infos(device_infos, kMaxCount);
if (count == 0) {
throw new Exception("Failed to get any audio device info");
}
if (count > 16) {
ou_free_audio_device_infos(device_infos, 16);
count = ou_get_audio_device_infos(device_infos, count);
if (count > kMaxCount) {
Log.Warning($"More than {kMaxCount} audio devices found, only the first {kMaxCount} will be listed.");
count = kMaxCount;
}
for (int i = 0; i < count; i++) {
var guidData = new byte[16];
fixed (byte* guidPtr = guidData) {
*(ulong*)guidPtr = device_infos[i].api_id;
*(ulong*)(guidPtr + 8) = device_infos[i].id;
}
string api = Marshal.PtrToStringUTF8(device_infos[i].api); // Should be ascii.
string name = (OS.IsWindows() && api != "WASAPI")
? Marshal.PtrToStringAnsi(device_infos[i].name)
: Marshal.PtrToStringUTF8(device_infos[i].name);
devices.Add(new AudioOutputDevice {
name = OS.IsWindows()
? Marshal.PtrToStringAnsi(device_infos[i].name)
: Marshal.PtrToStringUTF8(device_infos[i].name),
api = OS.IsWindows()
? Marshal.PtrToStringAnsi(device_infos[i].api)
: Marshal.PtrToStringUTF8(device_infos[i].api),
name = name,
api = api,
deviceNumber = i,
guid = new Guid(guidData),
});
Expand Down Expand Up @@ -111,15 +113,15 @@ private unsafe void DataCallback(float* buffer, uint channels, uint frame_count)
}
int n = 0;
if (sampleProvider != null) {
n = sampleProvider.Read(temp, 0, temp.Length);
n = sampleProvider.Read(temp, 0, samples);
}
if (n < samples) {
Array.Fill(temp, 0, n, samples - n);
}
if (n == 0) {
eof = true;
}
Marshal.Copy(temp, 0, (IntPtr)buffer, temp.Length);
Marshal.Copy(temp, 0, (IntPtr)buffer, samples);
currentTimeMs += n / channels * 1000.0 / sampleRate;
}

Expand Down
21 changes: 20 additions & 1 deletion cpp/worldline/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,28 @@ package(
default_visibility = ["//visibility:public"],
)

cc_binary(
name = "audio_debug",
srcs = ["audio_debug.cc"],
deps = [
":audio_output_lib",
"@absl//absl/debugging:failure_signal_handler",
"@absl//absl/debugging:symbolize",
"@absl//absl/flags:flag",
"@absl//absl/flags:parse",
"@absl//absl/log",
"@absl//absl/log:check",
"@absl//absl/log:initialize",
"@absl//absl/strings",
"@absl//absl/strings:string_view",
"@miniaudio",
"@xxhash",
],
)

cc_library(
name = "audio_output_lib",
srcs = ["audio_output.c"],
srcs = ["audio_output.cc"],
hdrs = ["audio_output.h"],
deps = [
"@miniaudio",
Expand Down
74 changes: 74 additions & 0 deletions cpp/worldline/audio_debug.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include <cstdint>

#include "absl/debugging/failure_signal_handler.h"
#include "absl/debugging/symbolize.h"
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/log/globals.h"
#include "absl/log/initialize.h"
#include "absl/log/log.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "miniaudio.h"
#include "worldline/audio_output.h"
#include "xxhash.h"

int main(int argc, char** argv) {
absl::InitializeSymbolizer(argv[0]);
absl::FailureSignalHandlerOptions options;
absl::InstallFailureSignalHandler(options);

absl::InitializeLog();
absl::SetStderrThreshold(absl::LogSeverity::kInfo);

absl::ParseCommandLine(argc, argv);

for (int i = 0; i < ma_backend_coreaudio; i++) {
LOG(INFO) << "============";
LOG(INFO) << "Trying backend: " << ma_get_backend_name((ma_backend)i);

ma_context context;
ma_backend backends[1] = {(ma_backend)i};
ma_result result = ma_context_init(backends, 1, NULL, &context);

if (result != MA_SUCCESS) {
LOG(ERROR) << "Failed to initialize context";
LOG(ERROR) << "Error: " << ma_result_description(result);
continue;
}

ma_device_info* playback_device_infos;
ma_uint32 playback_device_count;
ma_device_info* capture_device_infos;
ma_uint32 capture_device_count;

result = ma_context_get_devices(
&context, &playback_device_infos, &playback_device_count,
&capture_device_infos, &capture_device_count);

if (result != MA_SUCCESS) {
LOG(ERROR) << "Failed to get devices";
LOG(ERROR) << "Error: " << ma_result_description(result);
ma_context_uninit(&context);
continue;
}
LOG(INFO) << "Playback device count: " << playback_device_count;

for (int j = 0; j < playback_device_count; j++) {
LOG(INFO) << "------------";
LOG(INFO) << "Device: #" << j;
ma_device_info* info = &playback_device_infos[j];
LOG(INFO) << "Device name: " << info->name;
LOG(INFO) << "Device name bytes: "
<< absl::BytesToHexString(std::string_view(info->name));
uint64_t id = XXH64(&(info->id), sizeof(ma_device_id), 0);
LOG(INFO) << "Device ID: " << absl::Hex(id);
}
}

LOG(INFO) << "============";
LOG(INFO) << "Done";

return 0;
}
20 changes: 8 additions & 12 deletions cpp/worldline/audio_output.c → cpp/worldline/audio_output.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ DLL_API int32_t ou_get_audio_device_infos(ou_audio_device_info_t* device_infos,

for (int i = 0; i < ma_backend_null; i++) {
backends[0] = (ma_backend)i;
if (i == 0 || i == (int)ma_backend_dsound) {
backends[0] =
(ma_backend)((int)ma_backend_dsound - i); // Swaps dsound to first.
}
ma_result result = ma_context_init(backends, 1, NULL, &context);
if (result != MA_SUCCESS) {
continue;
Expand Down Expand Up @@ -74,22 +70,22 @@ static void silence(float* buffer, uint32_t channels, uint32_t frame_count) {
static void data_callback(ma_device* pDevice, void* pOutput, const void* pInput,
ma_uint32 frameCount) {
if (g_data_callback == NULL) {
silence(pOutput, pDevice->playback.channels, frameCount);
silence((float*)pOutput, pDevice->playback.channels, frameCount);
} else {
g_data_callback(pOutput, pDevice->playback.channels, frameCount);
g_data_callback((float*)pOutput, pDevice->playback.channels, frameCount);
}
}

DLL_API ou_audio_context_t* ou_init_audio_device(
uint32_t api_id, uint64_t id, ou_audio_data_callback_t callback) {
ou_audio_context_t* result = malloc(sizeof(ou_audio_context_t));
ou_audio_context_t* result = new ou_audio_context_t();
if (result == NULL) {
return NULL;
}

ma_backend backends[1] = {(ma_backend)api_id};
if (ma_context_init(backends, 1, NULL, &result->context) != MA_SUCCESS) {
free(result);
delete result;
return NULL;
}

Expand All @@ -101,7 +97,7 @@ DLL_API ou_audio_context_t* ou_init_audio_device(
&playback_device_count, &capture_device_infos,
&capture_device_count) != MA_SUCCESS) {
ma_context_uninit(&result->context);
free(result);
delete result;
return NULL;
}

Expand All @@ -123,14 +119,14 @@ DLL_API ou_audio_context_t* ou_init_audio_device(

if (config.playback.pDeviceID == NULL) {
ma_context_uninit(&result->context);
free(result);
delete result;
return NULL;
}

if (ma_device_init(&result->context, &config, &result->device) !=
MA_SUCCESS) {
ma_context_uninit(&result->context);
free(result);
delete result;
return NULL;
}

Expand All @@ -143,7 +139,7 @@ DLL_API int ou_free_audio_device(ou_audio_context_t* context) {
if (result != MA_SUCCESS) {
return result;
}
free(context);
delete context;
return 0;
}

Expand Down
Binary file modified runtimes/win-arm64/native/worldline.dll
Binary file not shown.
Binary file modified runtimes/win-x64/native/worldline.dll
Binary file not shown.
Binary file modified runtimes/win-x86/native/worldline.dll
Binary file not shown.

0 comments on commit 6958d68

Please sign in to comment.