|
| 1 | +# libsoundio-d |
| 2 | +Translation from C to D of [libsoundio](https://github.com/andrewrk/libsoundio). |
| 3 | + |
| 4 | +Libsoundio is a library for cross-platform real-time audio input and output. |
| 5 | + |
| 6 | +It is licensed under the MIT License. |
| 7 | +The translation is not affiliated with the original project. |
| 8 | + |
| 9 | +Currently not all backends are translated. |
| 10 | + |
| 11 | +| Backend | Translated | Used for | |
| 12 | +|--------------------------------------------------------------------------|-----------------|--------------------------------------------| |
| 13 | +| [Jack](https://jackaudio.org) | 🟠 Yes (untested)| See [JACK FAQ](https://jackaudio.org/faq/) | |
| 14 | +| [Pulseaudio](https://en.wikipedia.org/wiki/PulseAudio) | ✔️ Yes | Linux (higher-level) | |
| 15 | +| [Alsa](https://en.wikipedia.org/wiki/Advanced_Linux_Sound_Architecture) | ✔️ Yes | Linux (lower-level) | |
| 16 | +| [WASAPI](https://docs.microsoft.com/en-us/windows/win32/coreaudio/wasapi)| ✔️ Yes | Windows | |
| 17 | +| [Core Audio](https://en.wikipedia.org/wiki/Core_Audio) | ❌ No | macOS | |
| 18 | +| Dummy | ✔️ Yes | Testing | |
| 19 | + |
| 20 | +### Usage |
| 21 | + |
| 22 | +Add this package as a dependency to your project. |
| 23 | + |
| 24 | +dub.sdl: |
| 25 | +``` |
| 26 | +dependency "libsoundio-d" version="~>1.0.0" |
| 27 | +``` |
| 28 | + |
| 29 | +dub.json: |
| 30 | +``` |
| 31 | +"dependencies": { |
| 32 | + "libsoundio-d": "~>1.0.0" |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +And then use it: |
| 37 | +```D |
| 38 | +import soundio.api; |
| 39 | +
|
| 40 | +void main() { |
| 41 | + SoundIo* soundio = soundio_create(); |
| 42 | + soundio_connect(soundio); |
| 43 | + // your app |
| 44 | + soundio_destroy(soundio); |
| 45 | +} |
| 46 | +``` |
| 47 | + |
| 48 | +The configuration should be automatically selected based on your platform, but you can also choose one explicitly: |
| 49 | +- linux |
| 50 | +- windows |
| 51 | +- dummy |
| 52 | + |
| 53 | +dub.sdl: |
| 54 | +``` |
| 55 | +subConfiguration "libsoundio-d" "dummy" |
| 56 | +``` |
| 57 | + |
| 58 | +dub.json: |
| 59 | +``` |
| 60 | +"subConfigurations": { |
| 61 | + "libsoundio-d": "dummy" |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +On Linux, you should have ALSA and PulseAudio installed (which you probably have by default, otherwise look up how to install it). |
| 66 | + |
| 67 | +The following version identifiers are used: |
| 68 | +- `SOUNDIO_HAVE_JACK` |
| 69 | +- `SOUNDIO_HAVE_PULSEAUDIO` |
| 70 | +- `SOUNDIO_HAVE_ALSA` |
| 71 | +- `SOUNDIO_HAVE_COREAUDIO` |
| 72 | +- `SOUNDIO_HAVE_WASAPI` |
| 73 | + |
| 74 | +**Run the examples** |
| 75 | + |
| 76 | +Assuming your current directory is the root of this repository: |
| 77 | +``` |
| 78 | +dub run libsoundio-d:sine |
| 79 | +dub run libsoundio-d:list-devices -- --short |
| 80 | +dub run libsoundio-d:microphone -- --latency 0.05 |
| 81 | +dub run libsoundio-d:record -- output.bin |
| 82 | +``` |
| 83 | + |
| 84 | +**Run the tests** |
| 85 | +``` |
| 86 | +dub run libsoundio-d:backend-disconnect-recover |
| 87 | +dub run libsoundio-d:latency |
| 88 | +dub run libsoundio-d:overflow |
| 89 | +dub run libsoundio-d:underflow |
| 90 | +dub run libsoundio-d:unit-tests |
| 91 | +``` |
| 92 | + |
| 93 | +### Translation events |
| 94 | + |
| 95 | +The translation is closely converting C-syntax to D-syntax, no attempt to change the style to idiomatic D has been made. |
| 96 | +There are a few exceptions where certain constructs had to be changed however. |
| 97 | + |
| 98 | +- ALSA defines certain structs with an unknown size at compile time. |
| 99 | +There are specific `alloca` macros that allocate these structs on the stack, and libsoundio uses these. |
| 100 | +I translated these with malloc and free variants, because alloca has its own share of problems. |
| 101 | + |
| 102 | +- Libsoundio has certain `static` functions with the same name across backends: both ALSA and Pulse have `probe_device` and `my_flush_events`. |
| 103 | +Since D does not have C's notion of `static` functions (even `private` functions emit symbols), this introduces a name clash. |
| 104 | +Worse, because DMD emits weak symbols, it gives no multiple definition error, but instead silently calls the wrong function: |
| 105 | +The Pulse backend calls `probe_device` from the alsa backend instead of its own. |
| 106 | +This is mitigated by making those functions `extern(D)` giving them unique names. |
| 107 | + |
| 108 | +- D does not have C bindings of `stdatomic.h`, so I used equivalent functionality from `core.atomic`. |
| 109 | +`core.atomic` has no direct equivalent of 'flag test and set'. |
| 110 | +I initially translated as `cas` (compare and swap), but return value needed to be negated. |
| 111 | +`atomicFetchAdd` was added in dmd 2.089 and is not supported in LDC as of 1.22, so I used `atomicOp!"+="` instead. |
| 112 | + |
| 113 | +- On Windows `InterlockedIncrement` and `InterlockedDecrement` are not in the shipped import library "Kernel32.lib". |
| 114 | +I replaced it with a corresponding `atomicOp!"+="` and `atomicOp!"-="`. |
| 115 | + |
| 116 | +- On 32-bit Windows, 64-bit atomic operations are not supported. |
| 117 | +The `SoundIoRingBuffer` uses `ulong` for its read and write offset, even on 32-bit. |
| 118 | +I changed these to a `size_t` instead. |
| 119 | + |
| 120 | +- Use of `fprintf(sderr, ...)` on Windows with `extern(C) main` triggers [issue 20532](https://issues.dlang.org/show_bug.cgi?id=20532). A custom `printf_stderr` function was made to work around this. |
0 commit comments