<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>nativeaudio, branch HEAD</title>
<subtitle>audio playback for Go</subtitle>
<entry>
<id>09b2213e78a95a05fec42efa8e334ded8d32b7ef</id>
<published>2026-09-23T17:58:59Z</published>
<updated>2026-09-23T17:58:59Z</updated>
<title type="text">nativeaudio: add standard justfile</title>
<link rel="alternate" type="text/html" href="commit/09b2213e78a95a05fec42efa8e334ded8d32b7ef.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 09b2213e78a95a05fec42efa8e334ded8d32b7ef
parent c7adf6fb145b50d5e016235d8f8c92b138465526
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 23 Sep 2026 14:58:59 -0300

nativeaudio: add standard justfile

Same build, release, clean, test, install recipes as every other repository.

</content>
</entry>
<entry>
<id>c7adf6fb145b50d5e016235d8f8c92b138465526</id>
<published>2026-09-21T10:30:21Z</published>
<updated>2026-09-21T10:30:21Z</updated>
<title type="text">docs: record that every native backend now streams</title>
<link rel="alternate" type="text/html" href="commit/c7adf6fb145b50d5e016235d8f8c92b138465526.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit c7adf6fb145b50d5e016235d8f8c92b138465526
parent 561ed97c1e04e65ca49c0aaae4f2f03e0524b342
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 21 Sep 2026 07:30:21 -0300

docs: record that every native backend now streams

Both items the TODO tracked are done, so the section goes with them.

</content>
</entry>
<entry>
<id>561ed97c1e04e65ca49c0aaae4f2f03e0524b342</id>
<published>2026-09-21T10:27:12Z</published>
<updated>2026-09-21T10:27:12Z</updated>
<title type="text">macos: decode incrementally rather than buffering behind Stream</title>
<link rel="alternate" type="text/html" href="commit/561ed97c1e04e65ca49c0aaae4f2f03e0524b342.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 561ed97c1e04e65ca49c0aaae4f2f03e0524b342
parent ddd625297bfd82b46b818f789ae25caa124b5ad2
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 21 Sep 2026 07:27:12 -0300

macos: decode incrementally rather than buffering behind Stream

The converter was already a pull loop; this drives it a chunk at a time
instead of running it to completion up front.

</content>
</entry>
<entry>
<id>ddd625297bfd82b46b818f789ae25caa124b5ad2</id>
<published>2026-09-21T10:10:42Z</published>
<updated>2026-09-21T10:10:42Z</updated>
<title type="text">ci: mirror the clone rather than the build&#39;s own checkout</title>
<link rel="alternate" type="text/html" href="commit/ddd625297bfd82b46b818f789ae25caa124b5ad2.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit ddd625297bfd82b46b818f789ae25caa124b5ad2
parent 25ab19931a4b7496d3891880ac33e80d2a53955c
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 21 Sep 2026 07:10:42 -0300

ci: mirror the clone rather than the build&#39;s own checkout

Every branch but main was landing under refs/remotes/origin, which
GitHub does not treat as a branch and never builds.

</content>
</entry>
<entry>
<id>25ab19931a4b7496d3891880ac33e80d2a53955c</id>
<published>2026-09-21T10:10:24Z</published>
<updated>2026-09-21T10:10:24Z</updated>
<title type="text">ci: point the mirror at the renamed github repository</title>
<link rel="alternate" type="text/html" href="commit/25ab19931a4b7496d3891880ac33e80d2a53955c.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 25ab19931a4b7496d3891880ac33e80d2a53955c
parent 958747be0e949b3dd16c5bb16cedb6ec2a5cb314
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 21 Sep 2026 07:10:24 -0300

ci: point the mirror at the renamed github repository

The old name still redirects, but the push warns and the redirect is not
something to keep relying on.

</content>
</entry>
<entry>
<id>958747be0e949b3dd16c5bb16cedb6ec2a5cb314</id>
<published>2026-09-19T18:10:27Z</published>
<updated>2026-09-19T18:10:27Z</updated>
<title type="text">ci: cross-compile the 32-bit Windows target</title>
<link rel="alternate" type="text/html" href="commit/958747be0e949b3dd16c5bb16cedb6ec2a5cb314.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 958747be0e949b3dd16c5bb16cedb6ec2a5cb314
parent 99be5fcbab64387d8de95c88dd7868030740c8ef
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 19 Sep 2026 15:10:27 -0300

ci: cross-compile the 32-bit Windows target

It is the only configuration in which internal/mf/callback_32.go is
compiled at all.

</content>
</entry>
<entry>
<id>99be5fcbab64387d8de95c88dd7868030740c8ef</id>
<published>2026-09-19T18:10:27Z</published>
<updated>2026-09-19T18:10:27Z</updated>
<title type="text">ci: run the suite under AddressSanitizer on Linux</title>
<link rel="alternate" type="text/html" href="commit/99be5fcbab64387d8de95c88dd7868030740c8ef.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 99be5fcbab64387d8de95c88dd7868030740c8ef
parent 87d71a25c6d58dc8ebef4d3c1d83a5c86a515206
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 19 Sep 2026 15:10:27 -0300

ci: run the suite under AddressSanitizer on Linux

The leak test reads Go&#39;s heap profile, so nothing else in the suite
would notice the linked backend leaking on the C side.

</content>
</entry>
<entry>
<id>87d71a25c6d58dc8ebef4d3c1d83a5c86a515206</id>
<published>2026-09-19T18:10:27Z</published>
<updated>2026-09-19T18:10:27Z</updated>
<title type="text">test: check the linked backend against the ffmpeg on the same machine</title>
<link rel="alternate" type="text/html" href="commit/87d71a25c6d58dc8ebef4d3c1d83a5c86a515206.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 87d71a25c6d58dc8ebef4d3c1d83a5c86a515206
parent a76078f6f04315c96eda344fe139037836a55900
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 19 Sep 2026 15:10:27 -0300

test: check the linked backend against the ffmpeg on the same machine

Both sides come from one install and move together, so unlike the
checked-in reference this comparison cannot go stale.

</content>
</entry>
<entry>
<id>a76078f6f04315c96eda344fe139037836a55900</id>
<published>2026-09-19T17:56:54Z</published>
<updated>2026-09-19T17:56:54Z</updated>
<title type="text">docs: describe the linked Linux backend and what linking implies</title>
<link rel="alternate" type="text/html" href="commit/a76078f6f04315c96eda344fe139037836a55900.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit a76078f6f04315c96eda344fe139037836a55900
parent 29feeef5d399bb0613c8094f07d63a8e8cdeb8ec
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 19 Sep 2026 14:56:54 -0300

docs: describe the linked Linux backend and what linking implies

Dynamic linking answers the static-linking concern; distro builds
configured with --enable-gpl are the case worth flagging.

</content>
</entry>
<entry>
<id>29feeef5d399bb0613c8094f07d63a8e8cdeb8ec</id>
<published>2026-09-19T17:56:54Z</published>
<updated>2026-09-19T17:56:54Z</updated>
<title type="text">test: compare decodes without the padding that varies by ffmpeg</title>
<link rel="alternate" type="text/html" href="commit/29feeef5d399bb0613c8094f07d63a8e8cdeb8ec.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 29feeef5d399bb0613c8094f07d63a8e8cdeb8ec
parent a4d54b52ff25999a2e0a71a39b8fd2ec135a353c
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 19 Sep 2026 14:56:54 -0300

test: compare decodes without the padding that varies by ffmpeg

The reference disagreed with current ffmpeg by 767 trailing frames of
silence, and by no audio at all.

</content>
</entry>
<entry>
<id>a4d54b52ff25999a2e0a71a39b8fd2ec135a353c</id>
<published>2026-09-19T17:56:54Z</published>
<updated>2026-09-19T17:56:54Z</updated>
<title type="text">ci: install the libav headers the linked backend needs</title>
<link rel="alternate" type="text/html" href="commit/a4d54b52ff25999a2e0a71a39b8fd2ec135a353c.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit a4d54b52ff25999a2e0a71a39b8fd2ec135a353c
parent 71cb9ce45f1126d155f9915976ae916a40841f09
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 19 Sep 2026 14:56:54 -0300

ci: install the libav headers the linked backend needs

Every cgo-enabled Linux target now compiles against libavcodec,
libavformat, libavutil and libswresample.

</content>
</entry>
<entry>
<id>71cb9ce45f1126d155f9915976ae916a40841f09</id>
<published>2026-09-19T17:56:54Z</published>
<updated>2026-09-19T17:56:54Z</updated>
<title type="text">libav: decode by linking ffmpeg instead of spawning it</title>
<link rel="alternate" type="text/html" href="commit/71cb9ce45f1126d155f9915976ae916a40841f09.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 71cb9ce45f1126d155f9915976ae916a40841f09
parent d53fc254c83b0e79366be2b65c998d48b4c5d992
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 19 Sep 2026 14:56:54 -0300

libav: decode by linking ffmpeg instead of spawning it

Output is bit-identical to the ffmpeg binary here, and decoding from
memory no longer needs a temporary file.

</content>
</entry>
<entry>
<id>d53fc254c83b0e79366be2b65c998d48b4c5d992</id>
<published>2026-09-18T17:17:16Z</published>
<updated>2026-09-18T17:17:16Z</updated>
<title type="text">docs: describe the new API, the versions and the measured format matrix</title>
<link rel="alternate" type="text/html" href="commit/d53fc254c83b0e79366be2b65c998d48b4c5d992.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit d53fc254c83b0e79366be2b65c998d48b4c5d992
parent e0de7f9288c498e931539c019b8abf03c9d11ca3
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:17:16 -0400

docs: describe the new API, the versions and the measured format matrix

The readme still described package-level functions that no longer exist,
said nothing about what formats go in, and carried a licence note that
was wrong.

The format matrix is measured rather than copied from vendor
documentation: CI runs the probe on each platform and publishes the
result. Both native backends turn out to decode far more than the AAC
this package was written for, and the only gap either has is WMA on
macOS. AAC profiles get their own table and a warning, since that is the
one place a gap is dangerous rather than limiting: a backend handling
only AAC-LC decodes a high efficiency file to half its sample rate and
reports success.

The licence note now says LGPL rather than GPL, which is what FFmpeg&#39;s
libraries are, and justifies the sub-process by where it leaves the
patent question rather than by a constraint that does not apply.

</content>
</entry>
<entry>
<id>e0de7f9288c498e931539c019b8abf03c9d11ca3</id>
<published>2026-09-18T17:17:16Z</published>
<updated>2026-09-18T17:17:16Z</updated>
<title type="text">go.mod: retract v1.0.0</title>
<link rel="alternate" type="text/html" href="commit/e0de7f9288c498e931539c019b8abf03c9d11ca3.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit e0de7f9288c498e931539c019b8abf03c9d11ca3
parent 21fbc828636f8e23d5c5423a968d2c0f959844f5
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:17:16 -0400

go.mod: retract v1.0.0

v1.0.0 was tagged and pushed while the API was still moving. It exposed
the package-level Start, End, Load, Decode and Play that a Decoder value
has since replaced, and it decoded 24-bit sources to 24-bit rather than
the s16le the package documents.

The proxy has that version cached, so its content cannot be changed.
Retracting is the mechanism Go provides instead: go get stops selecting
it and anyone already on it is told to move. pkg.go.dev reports no
importers, so this costs nobody anything.

The next tag takes over the v1 line rather than moving to v2. Removing
exported functions inside a major version is a semver violation, and
with no dependents it protects nobody while welding a /v2 suffix onto
every import path forever.

</content>
</entry>
<entry>
<id>21fbc828636f8e23d5c5423a968d2c0f959844f5</id>
<published>2026-09-18T17:17:01Z</published>
<updated>2026-09-18T17:17:01Z</updated>
<title type="text">test: probe what each platform decoder actually accepts</title>
<link rel="alternate" type="text/html" href="commit/21fbc828636f8e23d5c5423a968d2c0f959844f5.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 21fbc828636f8e23d5c5423a968d2c0f959844f5
parent d4b316c57aec5e79e2d391d715cf6de09919bb6a
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:17:01 -0400

test: probe what each platform decoder actually accepts

The operating system decoders handle far more than AAC, and which extras
they handle differs between them, but nothing measured it, so the readme
could only have claimed support from vendor documentation. This
generates a file per format with ffmpeg and reports what came back, and
probes the ffmpeg fallback alongside the native one wherever ffmpeg
exists, so a run on any platform fills in more than its own column.

Formats the readme claims are assertions; the rest are reported, which
is what lets CI publish the matrix. It skips without ffmpeg, and the
high efficiency AAC profiles need an encoder ffmpeg does not ship by
default, so those stay unmeasured.

</content>
</entry>
<entry>
<id>d4b316c57aec5e79e2d391d715cf6de09919bb6a</id>
<published>2026-09-18T17:17:00Z</published>
<updated>2026-09-18T17:17:00Z</updated>
<title type="text">test: fuzz the decode, stream and abandoned-stream paths</title>
<link rel="alternate" type="text/html" href="commit/d4b316c57aec5e79e2d391d715cf6de09919bb6a.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit d4b316c57aec5e79e2d391d715cf6de09919bb6a
parent 99210bf9e9b5a659df56b0ecf9160a898234b012
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:17:00 -0400

test: fuzz the decode, stream and abandoned-stream paths

Untrusted files are this package&#39;s main input, and on Windows and macOS
those bytes reach the operating system&#39;s own decoder through
hand-written bindings, so it is the surface most worth fuzzing. A branch
from 2022 started this with random bytes and a fixed seed; Go gained
native fuzzing that same year, so these are proper targets instead.

The property is that a decode either fails or returns a coherent result:
sane format, and PCM that is a whole number of frames. The streaming
targets matter separately because sample lifetime and buffer locking are
bookkeeping the buffered path does not exercise on the same schedule.

This found the decode that could not be recovered. The input is kept as
a fixture, and the test for it asserts that such a decode now gives up
promptly rather than running forever. The targets take a much tighter
budget than a normal caller would, because malformed audio can grind for
longer than the fuzzing harness tolerates before declaring a worker hung.

</content>
</entry>
<entry>
<id>99210bf9e9b5a659df56b0ecf9160a898234b012</id>
<published>2026-09-18T17:16:46Z</published>
<updated>2026-09-18T17:16:46Z</updated>
<title type="text">pcm: adapt the output to other audio stacks</title>
<link rel="alternate" type="text/html" href="commit/99210bf9e9b5a659df56b0ecf9160a898234b012.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 99210bf9e9b5a659df56b0ecf9160a898234b012
parent bb7c6e9615e66cd0e9501c91af87f3539c1915d9
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:16:46 -0400

pcm: adapt the output to other audio stacks

Being the decoder inside someone else&#39;s audio stack is a much larger
audience than being the whole stack, and the two conventions in Go are
an io.Reader of s16le, which a Stream already is, and pairs of float64
samples, which nothing here produced.

pcm.NewStreamer converts to the latter and satisfies beep&#39;s Streamer and
StreamCloser without importing beep, because Go interfaces are
structural and neither side needs to know about the other. The tests
restate those interfaces locally and assert against them, so a signature
drifting on either side shows up as a build failure rather than a
runtime surprise.

It takes an io.Reader rather than a Stream, so the buffered API works
through a bytes.Reader, and Close delegates when the reader owns decoder
state. Frames split across reads are buffered, which matters because the
backend does return partial frames. Mono is written to both channels,
and more than two channels keeps the first two rather than mixing down,
which is a decision the caller should make.

</content>
</entry>
<entry>
<id>bb7c6e9615e66cd0e9501c91af87f3539c1915d9</id>
<published>2026-09-18T17:16:45Z</published>
<updated>2026-09-18T17:16:45Z</updated>
<title type="text">play: bound the wait for playback to finish</title>
<link rel="alternate" type="text/html" href="commit/bb7c6e9615e66cd0e9501c91af87f3539c1915d9.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit bb7c6e9615e66cd0e9501c91af87f3539c1915d9
parent d5dde756fc3200d476325eda5c69f54e6ff9b4d4
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:16:45 -0400

play: bound the wait for playback to finish

PCM waited on IsPlaying with no bound. That is correct while the audio
device makes progress and a hang when it does not, which is exactly what
a machine with no sound hardware looks like: CI sat for the full test
timeout.

The audio&#39;s own length is the natural bound, so Duration computes it and
the wait allows that plus a quarter and ten seconds for the buffer and a
slow start. Past that the player is closed and the caller is told the
device is not progressing.

Duration is exported because a caller sizing its own timeout needs the
same number, and tested directly so the bound cannot quietly regress.

</content>
</entry>
<entry>
<id>d5dde756fc3200d476325eda5c69f54e6ff9b4d4</id>
<published>2026-09-18T17:16:18Z</published>
<updated>2026-09-18T17:16:18Z</updated>
<title type="text">mf: pin the decoder output to 16 bits per sample</title>
<link rel="alternate" type="text/html" href="commit/d5dde756fc3200d476325eda5c69f54e6ff9b4d4.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit d5dde756fc3200d476325eda5c69f54e6ff9b4d4
parent bf19fbe42f8f291e04a1ded34c3261a5c18007c3
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:16:18 -0400

mf: pin the decoder output to 16 bits per sample

Asking the source reader only for PCM lets it hand back whatever width
the source uses, so a 24-bit WAV decoded to 24-bit. That breaks the
s16le output the package documents and Format.BytesPerSample promises:
playback rejected it outright, and anything treating the bytes as int16
would have read garbage.

</content>
</entry>
<entry>
<id>bf19fbe42f8f291e04a1ded34c3261a5c18007c3</id>
<published>2026-09-18T17:16:17Z</published>
<updated>2026-09-18T17:16:17Z</updated>
<title type="text">mf: make a wedged decode abandonable</title>
<link rel="alternate" type="text/html" href="commit/bf19fbe42f8f291e04a1ded34c3261a5c18007c3.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit bf19fbe42f8f291e04a1ded34c3261a5c18007c3
parent ce90339d90026caf72cdf791283ad97687f574e7
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:16:17 -0400

mf: make a wedged decode abandonable

Fuzzing found a half-megabyte file that Media Foundation never finishes
decoding. It opens cleanly, reports a plausible format, then grinds out
a few hundred kilobytes of PCM and stops answering. The decode could not
be recovered: ReadSample was synchronous, so the blocked call owned the
calling thread and nothing could interrupt it.

The source reader now runs asynchronously, which needs a COM callback,
which means implementing IMFSourceReaderCallback in Go. A COM interface
pointer is a struct whose first word points to a vtable, so a Go struct
with a vtable of syscall.NewCallback trampolines as its first field is a
usable COM object. The vtable is a package singleton because those
trampolines are never freed, the object is refcounted and pinned because
Media Foundation holds its address, and every method runs under a
recover: a panic crossing those frames would take the process down. The
64-bit timestamp argument is the only thing that differs by word size,
so it lives in two small build-tagged files and is ignored in favour of
reading the time back off the sample. The retry loop is bounded too,
since asking for a sample and being given nothing is otherwise unlimited.

Waiting is then ours to bound. Limits caps how long a decode may run and
how much it may produce, with a finite default, and the deadline reaches
the backend so a read already parked on the decoder gives up with
everything else. The buffered API is routed through the streaming one so
both are covered.

That leaves teardown. Releasing a source reader waits for Media
Foundation to finish, which after a clean end of stream is immediate and
after a wedged decode is never: flushing the reader and closing the byte
stream underneath it were both measured to make no difference, and one
blocked release was watched for ten minutes without returning.

Such a reader is leaked rather than released on a goroutine. A release
that never returns never frees anything either, so waiting on it leaks
the same objects and adds a thread: waiting is a superset of not
waiting. The thread costs no CPU, since one parked in a blocking system
call is never scheduled, but the runtime caps a process at 10000 threads
and crossing that is fatal. At roughly one thread per bad file that
ceiling is reachable by a program decoding untrusted input.

</content>
</entry>
<entry>
<id>ce90339d90026caf72cdf791283ad97687f574e7</id>
<published>2026-09-18T17:15:45Z</published>
<updated>2026-09-18T17:15:45Z</updated>
<title type="text">audio: [macOS] do not read the packet description out-parameter</title>
<link rel="alternate" type="text/html" href="commit/ce90339d90026caf72cdf791283ad97687f574e7.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit ce90339d90026caf72cdf791283ad97687f574e7
parent 91ddb316f6d25fff5af17efb71809a147905397d
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:15:45 -0400

audio: [macOS] do not read the packet description out-parameter

The converter&#39;s input callback passed packet descriptions along to the
file reader by reading them back out of its own out-parameter. That only
works for variable bitrate input, where the callback has just written
them. Constant bitrate input has no packet descriptions, so the
parameter arrives uninitialised and the reader was handed whatever
happened to be on the stack.

Nothing caught it because the only fixture was AAC, which is variable
bitrate. The first constant bitrate input to reach this code, a plain
WAV from the format tests, wedged the converter until the test timeout.

The callback now keeps its own pointer, nil unless it has descriptions
to give, and writes it out rather than reading it back.

</content>
</entry>
<entry>
<id>91ddb316f6d25fff5af17efb71809a147905397d</id>
<published>2026-09-18T17:15:44Z</published>
<updated>2026-09-18T17:15:44Z</updated>
<title type="text">audio: [macOS] report the buffer length, not its capacity</title>
<link rel="alternate" type="text/html" href="commit/91ddb316f6d25fff5af17efb71809a147905397d.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 91ddb316f6d25fff5af17efb71809a147905397d
parent c79f169bf107942fba9ce8208fc7d1673764af13
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:15:44 -0400

audio: [macOS] report the buffer length, not its capacity

The size callback told AudioToolbox the file was cap(buf) bytes. A slice
built by append or returned by io.ReadAll usually has room to spare, so
the decoder was told there was more audio than there was, kept asking
for data past the end, and got short reads reported as success. It never
stopped: a generated WAV hung the decode until the test timeout.

The fixture this package has always tested with is embedded, where
capacity equals length, so the bug never showed. Every generated one has
spare capacity, and so does anything read with io.ReadAll, which is how
the file entry point builds its buffer.

The read callback now clamps the start as well as the end. Clamping only
the end left a start past the finish, which panics inside a C callback
and takes the process with it.

</content>
</entry>
<entry>
<id>c79f169bf107942fba9ce8208fc7d1673764af13</id>
<published>2026-09-18T17:15:43Z</published>
<updated>2026-09-18T17:15:43Z</updated>
<title type="text">audio: [macOS] pass caller data to AudioToolbox as cgo handles</title>
<link rel="alternate" type="text/html" href="commit/c79f169bf107942fba9ce8208fc7d1673764af13.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit c79f169bf107942fba9ce8208fc7d1673764af13
parent ab99185806a086f2ce26c222dbc59384f051f87c
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:15:43 -0400

audio: [macOS] pass caller data to AudioToolbox as cgo handles

go vet on macOS flagged OpenAudioFileBuffer for handing C a pointer to a
Go slice header. It is a real violation rather than a nit: the rules
forbid giving C Go memory that itself contains Go pointers, and
AudioToolbox keeps this caller data and calls back through it long after
the call returns. Pinning does not make that legal, and it held only
because the collector does not move objects today.

The converter context went across the same way, and it holds both a
pointer and a slice.

Both now travel as runtime/cgo handles, which is what handles are for:
an opaque integer the runtime resolves back to the value, keeping it
alive without C ever seeing a Go pointer. Widening the handle to the
void* these interfaces want is done in C, since doing it in Go is the
same rule violation in a different costume. The file&#39;s handle is
released when it is disposed and the converter&#39;s when the decode
returns.

</content>
</entry>
<entry>
<id>ab99185806a086f2ce26c222dbc59384f051f87c</id>
<published>2026-09-18T17:15:42Z</published>
<updated>2026-09-18T17:15:42Z</updated>
<title type="text">audio: bound the teardown of an abandoned ffmpeg stream</title>
<link rel="alternate" type="text/html" href="commit/ab99185806a086f2ce26c222dbc59384f051f87c.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit ab99185806a086f2ce26c222dbc59384f051f87c
parent d33392d0fd7c0fa984698cd6670b5081a8be247f
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:15:42 -0400

audio: bound the teardown of an abandoned ffmpeg stream

Closing a stream that was not drained killed the process and then waited
for it, which assumed the kill worked. On a runner whose ffmpeg comes
through a launcher shim it does not: killing the shim leaves the real
process alive holding the pipe, so the wait never returned and Close
hung.

Teardown now has a deadline. Whatever still holds the pipe finishes
decoding shortly and exits by itself, so this is a brief leak rather
than a caller that cannot return. Draining the pipe before waiting also
observes the contract the standard library documents, which the previous
version quietly broke.

</content>
</entry>
<entry>
<id>d33392d0fd7c0fa984698cd6670b5081a8be247f</id>
<published>2026-09-18T17:15:18Z</published>
<updated>2026-09-18T17:15:18Z</updated>
<title type="text">audio: add a streaming decode API</title>
<link rel="alternate" type="text/html" href="commit/d33392d0fd7c0fa984698cd6670b5081a8be247f.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit d33392d0fd7c0fa984698cd6670b5081a8be247f
parent 4204f85890a6af43cf105af3a3e14df76c12a741
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:15:18 -0400

audio: add a streaming decode API

The only way to decode was into one buffer, and PCM runs roughly an
order of magnitude larger than the compressed input. A few minutes of
stereo audio is tens of megabytes, which rules the package out for long
files and for anything feeding a pipeline incrementally.

Stream and StreamFile return an io.Reader over the same PCM, with the
format known before the first read. Windows decodes incrementally: the
Media Foundation objects move into a Stream that owns and releases them,
where before they were built and torn down inside one call. The ffmpeg
backend pipes straight out of the process rather than buffering, and
reaps its child whether the stream is drained or abandoned. macOS still
decodes up front behind the same interface, so behaviour is uniform and
that backend can improve without another API change.

Abandoning a stream mid-decode no longer strands a locked Media
Foundation buffer, and closing a Decoder now waits for open streams
before releasing the platform state they are still using.

</content>
</entry>
<entry>
<id>4204f85890a6af43cf105af3a3e14df76c12a741</id>
<published>2026-09-18T17:15:16Z</published>
<updated>2026-09-18T17:15:16Z</updated>
<title type="text">audio: replace the global API with a Decoder value</title>
<link rel="alternate" type="text/html" href="commit/4204f85890a6af43cf105af3a3e14df76c12a741.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 4204f85890a6af43cf105af3a3e14df76c12a741
parent debd8ef9f7a7621c307396ef79546bc5a084a245
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:15:16 -0400

audio: replace the global API with a Decoder value

Start, End, Load and Decode operated on hidden package state guarded by
a mutex and an initialised flag. Two parts of a program could not each
hold their own decoder, and either could call End and tear the platform
out from under the other. Every decode also had to call Start
implicitly, so initialisation failures surfaced in unrelated places.

New returns a Decoder that owns the platform state and Close releases
it. Media Foundation refcounts startup against shutdown, so independent
decoders coexist, which a new test pins down. Use after Close returns
ErrClosed rather than misbehaving, and the read lock lets decodes run
concurrently while Close waits for those in flight.

The Media Foundation entry points are now resolved once per process
instead of on every startup, since the handles outlive any one decoder.

</content>
</entry>
<entry>
<id>debd8ef9f7a7621c307396ef79546bc5a084a245</id>
<published>2026-09-18T17:15:02Z</published>
<updated>2026-09-18T17:15:02Z</updated>
<title type="text">play: move playback into its own package</title>
<link rel="alternate" type="text/html" href="commit/debd8ef9f7a7621c307396ef79546bc5a084a245.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit debd8ef9f7a7621c307396ef79546bc5a084a245
parent 026e4b1809410e8c68396eb12f5c58ea8141c5c8
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:15:02 -0400

play: move playback into its own package

Decoding is the reason this package exists, and most callers want PCM to
feed an audio stack they have already chosen. Keeping playback in the
core meant every consumer inherited an output stack they might not use,
along with its process-wide context limitation, which had to be
documented as a caveat on an otherwise simple decode API.

Playback now lives in the play subpackage and goes through oto on every
platform rather than oto on two and ffplay on the rest. That drops the
external ffplay dependency and makes playback behave the same
everywhere, so FFmpegPlay is gone with it. The core package no longer
links oto at all.

</content>
</entry>
<entry>
<id>026e4b1809410e8c68396eb12f5c58ea8141c5c8</id>
<published>2026-09-18T17:14:41Z</published>
<updated>2026-09-18T17:14:41Z</updated>
<title type="text">ci: build, test and diagnose on Linux, Windows and macOS</title>
<link rel="alternate" type="text/html" href="commit/026e4b1809410e8c68396eb12f5c58ea8141c5c8.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 026e4b1809410e8c68396eb12f5c58ea8141c5c8
parent 6a7c98d26b76c0c93b56884040d8d14392a5c21c
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 18 Sep 2026 13:14:41 -0400

ci: build, test and diagnose on Linux, Windows and macOS

The whole package is platform-specific native bindings, and nothing
compiled the macOS decoder, let alone ran it. The sr.ht build only
mirrors to GitHub, and builds.sr.ht offers no Windows or macOS images,
so the matrix lives on GitHub Actions where standard runners are free
for public repositories.

A second job builds every GOOS, GOARCH and cgo combination, keeping the
core package separate from the playback one: the core is meant to build
anywhere, while playback is bounded by what its audio backend supports.

Failures are reported as annotations and in the job summary because raw
logs need a sign-in and this repository is a mirror people reach without
credentials. The format support matrix is published the same way, one
annotation per platform, so the table in the readme comes from machines.

Go sources are pinned to LF, since a checkout on Windows would otherwise
convert them and gofmt reports a CRLF file as unformatted.

</content>
</entry>
<entry>
<id>6a7c98d26b76c0c93b56884040d8d14392a5c21c</id>
<published>2026-09-17T16:09:48Z</published>
<updated>2026-09-17T16:11:17Z</updated>
<title type="text">docs: describe the public API and the v1.0.0 breaking changes</title>
<link rel="alternate" type="text/html" href="commit/6a7c98d26b76c0c93b56884040d8d14392a5c21c.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 6a7c98d26b76c0c93b56884040d8d14392a5c21c
parent e63bbc49b6a3d4b85606a5cc85c187a57ae6f09b
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 17 Sep 2026 12:09:48 -0400

docs: describe the public API and the v1.0.0 breaking changes

</content>
</entry>
<entry>
<id>e63bbc49b6a3d4b85606a5cc85c187a57ae6f09b</id>
<published>2026-09-17T16:09:48Z</published>
<updated>2026-09-17T16:11:17Z</updated>
<title type="text">audio: fix inverted package comment and document the Play format limit</title>
<link rel="alternate" type="text/html" href="commit/e63bbc49b6a3d4b85606a5cc85c187a57ae6f09b.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit e63bbc49b6a3d4b85606a5cc85c187a57ae6f09b
parent 3bdbe9d9e5d2e907bf64e2d33492e9a4e5648f9a
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 17 Sep 2026 12:09:48 -0400

audio: fix inverted package comment and document the Play format limit

The package comment said ffmpeg is used where native APIs exist, the
opposite of the design. Spell ffmpeg correctly and note on Play that the
Windows and macOS playback context is fixed to the first file&#39;s format.

</content>
</entry>
<entry>
<id>3bdbe9d9e5d2e907bf64e2d33492e9a4e5648f9a</id>
<published>2026-09-17T15:58:20Z</published>
<updated>2026-09-17T16:11:16Z</updated>
<title type="text">test: cover the ffmpeg fallbacks when ffmpeg is installed</title>
<link rel="alternate" type="text/html" href="commit/3bdbe9d9e5d2e907bf64e2d33492e9a4e5648f9a.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 3bdbe9d9e5d2e907bf64e2d33492e9a4e5648f9a
parent 87ea90df507740bf93d4cf2840953b0b38977098
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 17 Sep 2026 11:58:20 -0400

test: cover the ffmpeg fallbacks when ffmpeg is installed

FFmpegLoad, FFmpegDecode and FFmpegPlay had no tests, which is how a
mistyped ffplay flag shipped. They now run wherever ffmpeg is on PATH,
including Windows, so the fallback is checked without a Linux machine.
Load and Decode must agree exactly with each other and match the
ffmpeg-produced reference; FFmpegPlay must block for the file&#39;s duration.

</content>
</entry>
<entry>
<id>87ea90df507740bf93d4cf2840953b0b38977098</id>
<published>2026-09-17T15:58:19Z</published>
<updated>2026-09-17T16:11:16Z</updated>
<title type="text">test: play a silent file twice and check each call runs full length</title>
<link rel="alternate" type="text/html" href="commit/87ea90df507740bf93d4cf2840953b0b38977098.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 87ea90df507740bf93d4cf2840953b0b38977098
parent 9ffd7724e3c2f8bec605d5b958910a57f6bb930d
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 17 Sep 2026 11:58:19 -0400

test: play a silent file twice and check each call runs full length

Play was untested, so neither a second call failing on the process-wide
audio context nor the tail being cut off when the source hit EOF could
be caught. A generated second of silence keeps the test quiet; timing
bounds catch an early return, and the second iteration catches a context
that cannot be reused. Skips when no audio output is available.

</content>
</entry>
<entry>
<id>9ffd7724e3c2f8bec605d5b958910a57f6bb930d</id>
<published>2026-09-17T15:57:34Z</published>
<updated>2026-09-17T16:11:16Z</updated>
<title type="text">test: cover more formats, Start/End cycles and mid-stream corruption</title>
<link rel="alternate" type="text/html" href="commit/9ffd7724e3c2f8bec605d5b958910a57f6bb930d.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 9ffd7724e3c2f8bec605d5b958910a57f6bb930d
parent a55f0ac25fe2b1ee2ca99ad323d1e9370e999801
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 17 Sep 2026 11:57:34 -0400

test: cover more formats, Start/End cycles and mid-stream corruption

The suite decoded one 44.1 kHz stereo AAC file and nothing else, so End
was never called and Format was only ever checked for that one shape.
A generated silent WAV gives mono and other sample rates without
fixtures. The mid-stream corruption test is a hang guard: the sample
reader used to spin forever when the decoder returned neither a sample
nor an end-of-stream flag.

</content>
</entry>
<entry>
<id>a55f0ac25fe2b1ee2ca99ad323d1e9370e999801</id>
<published>2026-09-17T01:31:13Z</published>
<updated>2026-09-17T16:11:16Z</updated>
<title type="text">test: require equal length and allow under 1 LSB mean error</title>
<link rel="alternate" type="text/html" href="commit/a55f0ac25fe2b1ee2ca99ad323d1e9370e999801.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit a55f0ac25fe2b1ee2ca99ad323d1e9370e999801
parent 878fc355ded97993497419d131540f000344d499
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:31:13 -0400

test: require equal length and allow under 1 LSB mean error

Media Foundation and ffmpeg both decode the fixture to the same number
of samples, but their AAC implementations round differently: mean
absolute error is 0.46 with a maximum of 415 out of 32768. The 0.1
threshold treated that as failure, so the suite was red at HEAD. Compare
lengths exactly, then accept a mean absolute difference below one
quantisation step.

</content>
</entry>
<entry>
<id>878fc355ded97993497419d131540f000344d499</id>
<published>2026-09-17T01:44:53Z</published>
<updated>2026-09-17T16:11:16Z</updated>
<title type="text">audio: rename Format.BitDepth to BytesPerSample</title>
<link rel="alternate" type="text/html" href="commit/878fc355ded97993497419d131540f000344d499.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 878fc355ded97993497419d131540f000344d499
parent f5f38413db88956b1dd02b48e023119e25b9e40e
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:44:53 -0400

audio: rename Format.BitDepth to BytesPerSample

The field held bytes per sample (2 for s16le) while its name implied
bits (16). Renaming rather than changing the value forces callers to
notice: a silent 2 to 16 change would compile and then mis-size every
buffer. The macOS decoder is updated alongside the Windows and ffmpeg
paths.

</content>
</entry>
<entry>
<id>f5f38413db88956b1dd02b48e023119e25b9e40e</id>
<published>2026-09-17T01:37:59Z</published>
<updated>2026-09-17T16:11:15Z</updated>
<title type="text">mf: move Media Foundation bindings into an internal package</title>
<link rel="alternate" type="text/html" href="commit/f5f38413db88956b1dd02b48e023119e25b9e40e.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit f5f38413db88956b1dd02b48e023119e25b9e40e
parent 399c519613fcd74458a58e172931e8abce85523f
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:37:59 -0400

mf: move Media Foundation bindings into an internal package

The COM vtables, GUIDs, MF* entry points and SourceReader were exported
from the root package on Windows, so they showed up in the public API
and could be called before Start had loaded the DLLs, which panics on a
nil proc. They now live in internal/mf behind Startup, Shutdown and
Decode. The identifiers keep their SDK names inside the package so they
can be checked against the headers. The root package now exports only
Start, End, Play, Load, Decode, Format and the FFmpeg fallbacks.

</content>
</entry>
<entry>
<id>399c519613fcd74458a58e172931e8abce85523f</id>
<published>2026-09-17T01:31:14Z</published>
<updated>2026-09-17T16:11:15Z</updated>
<title type="text">internal: remove unused TriggerReader</title>
<link rel="alternate" type="text/html" href="commit/399c519613fcd74458a58e172931e8abce85523f.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 399c519613fcd74458a58e172931e8abce85523f
parent be6e3d2572b9cd2bcbfc0ea9b55b6f71774ea39c
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:31:14 -0400

internal: remove unused TriggerReader

Windows playback now waits on the player&#39;s own IsPlaying state, which
covers both source exhaustion and buffer drain, so nothing reads through
the trigger any more.

</content>
</entry>
<entry>
<id>be6e3d2572b9cd2bcbfc0ea9b55b6f71774ea39c</id>
<published>2026-09-17T16:09:23Z</published>
<updated>2026-09-17T16:11:15Z</updated>
<title type="text">audio: share one oto playback context and wait for the buffer to drain</title>
<link rel="alternate" type="text/html" href="commit/be6e3d2572b9cd2bcbfc0ea9b55b6f71774ea39c.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit be6e3d2572b9cd2bcbfc0ea9b55b6f71774ea39c
parent 1f7e8a70d558e0b31085092b28648558188e9b21
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 17 Sep 2026 12:09:23 -0400

audio: share one oto playback context and wait for the buffer to drain

Windows and macOS each created an oto context inside play. oto permits
one context per process, so every Play after the first failed with
&quot;context is already created&quot;. Both also returned as soon as the source
hit EOF, which is when oto has buffered the data rather than played it,
cutting up to half a second from the tail.

playback.go now holds the shared path: a context created on first use
and reused, a clear error for a later file whose sample rate or channel
count differs, and a wait on IsPlaying, which stays true until the buffer
has drained. Both platform play functions reduce to decode then playPCM.

The macOS build was not compiled for this change; its play body is a
two-line call into code exercised on Windows.

</content>
</entry>
<entry>
<id>1f7e8a70d558e0b31085092b28648558188e9b21</id>
<published>2026-09-17T01:29:38Z</published>
<updated>2026-09-17T16:11:15Z</updated>
<title type="text">audio: use os.CreateTemp for the ffmpeg decode scratch file</title>
<link rel="alternate" type="text/html" href="commit/1f7e8a70d558e0b31085092b28648558188e9b21.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 1f7e8a70d558e0b31085092b28648558188e9b21
parent 0c9c77611e8067c20f4e99b7fc374434a54904c0
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:29:38 -0400

audio: use os.CreateTemp for the ffmpeg decode scratch file

The scratch file was named from a process-local counter, so two
processes decoding at once both wrote nativeaudio-1 and could corrupt
each other&#39;s input. os.CreateTemp guarantees a unique name and lets the
unused counter type go.

</content>
</entry>
<entry>
<id>0c9c77611e8067c20f4e99b7fc374434a54904c0</id>
<published>2026-09-17T01:29:00Z</published>
<updated>2026-09-17T16:11:14Z</updated>
<title type="text">audio: fix ffplay -autoexit flag</title>
<link rel="alternate" type="text/html" href="commit/0c9c77611e8067c20f4e99b7fc374434a54904c0.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 0c9c77611e8067c20f4e99b7fc374434a54904c0
parent 347b25f8f9aca4e94382b3029d4492664967a9ea
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:29:00 -0400

audio: fix ffplay -autoexit flag

The flag was spelled -autoext, which ffplay rejects with &quot;Missing
argument for option&quot;, so FFmpegPlay failed on every call.

</content>
</entry>
<entry>
<id>347b25f8f9aca4e94382b3029d4492664967a9ea</id>
<published>2026-09-17T01:29:00Z</published>
<updated>2026-09-17T16:11:14Z</updated>
<title type="text">audio: [Windows] satisfy go vet on the IStream pointer conversion</title>
<link rel="alternate" type="text/html" href="commit/347b25f8f9aca4e94382b3029d4492664967a9ea.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 347b25f8f9aca4e94382b3029d4492664967a9ea
parent 32313045de260b778f0f6b76bbacfa1154136599
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:29:00 -0400

audio: [Windows] satisfy go vet on the IStream pointer conversion

vet flagged the uintptr to pointer cast for the shell-owned COM
interface. The pointer is not Go memory so the cast is safe; converting
through the address of the uintptr expresses that without a warning and
keeps `go vet ./...` clean.

</content>
</entry>
<entry>
<id>32313045de260b778f0f6b76bbacfa1154136599</id>
<published>2026-09-17T01:28:25Z</published>
<updated>2026-09-17T16:11:14Z</updated>
<title type="text">audio: [Windows] surface source reader errors instead of looping</title>
<link rel="alternate" type="text/html" href="commit/32313045de260b778f0f6b76bbacfa1154136599.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 32313045de260b778f0f6b76bbacfa1154136599
parent 6a28e1fb185cdd2edf9a9cef7c6200d031a4d3cc
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:28:25 -0400

audio: [Windows] surface source reader errors instead of looping

ReadSample, ConvertToContiguousBuffer and Lock results were discarded.
A mid-stream decode failure leaves the sample nil and sets only
MF_SOURCE_READERF_ERROR, which the loop did not test, so next() spun on
ReadSample forever. A failed Lock would have handed a nil pointer to
unsafe.Slice. Errors now propagate through Read, a media type change is
reported rather than silently truncating, and samples that are skipped
for repeating a timestamp or that arrive with a terminal flag are
released instead of leaked. The timestamp bookkeeping drops the
prevTimestamp-1 trick for an explicit hasPrev flag.

</content>
</entry>
<entry>
<id>6a28e1fb185cdd2edf9a9cef7c6200d031a4d3cc</id>
<published>2026-09-17T01:26:54Z</published>
<updated>2026-09-17T16:11:14Z</updated>
<title type="text">audio: [Windows] call MFShutdown from End</title>
<link rel="alternate" type="text/html" href="commit/6a28e1fb185cdd2edf9a9cef7c6200d031a4d3cc.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 6a28e1fb185cdd2edf9a9cef7c6200d031a4d3cc
parent e8bf58c33b5795abb6799a7ed58d65fbc570c14b
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:26:54 -0400

audio: [Windows] call MFShutdown from End

MFShutdown invoked the MFStartup proc, so End never released Media
Foundation and instead bumped its startup count each time. The mistake
was silent because MFStartup returns S_OK when the platform is already
running.

</content>
</entry>
<entry>
<id>e8bf58c33b5795abb6799a7ed58d65fbc570c14b</id>
<published>2026-09-17T01:26:39Z</published>
<updated>2026-09-17T16:11:14Z</updated>
<title type="text">audio: [Windows] release COM objects after they are created</title>
<link rel="alternate" type="text/html" href="commit/e8bf58c33b5795abb6799a7ed58d65fbc570c14b.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit e8bf58c33b5795abb6799a7ed58d65fbc570c14b
parent 852abf67ebee4d6f5007240ef33c78a8fb2b3d43
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:26:39 -0400

audio: [Windows] release COM objects after they are created

`defer x.Release()` evaluates the receiver at the defer statement. Every
Media Foundation object was deferred before the call that assigned it,
so each Release ran against a nil pointer and did nothing. The byte
stream, attributes, source reader and both media types leaked on every
decode. Deferring after the creating call succeeds fixes the leak and
also avoids a Release on a pointer that was never assigned when the call
fails.

</content>
</entry>
<entry>
<id>852abf67ebee4d6f5007240ef33c78a8fb2b3d43</id>
<published>2026-09-17T01:27:25Z</published>
<updated>2026-09-17T16:11:13Z</updated>
<title type="text">audio: [Windows] use uint32 for DWORD parameters</title>
<link rel="alternate" type="text/html" href="commit/852abf67ebee4d6f5007240ef33c78a8fb2b3d43.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 852abf67ebee4d6f5007240ef33c78a8fb2b3d43
parent ca92fe50f56e07bb9c6cf1b85ef8f3bb2a9411df
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:27:25 -0400

audio: [Windows] use uint32 for DWORD parameters

Stream indices, stream flags and buffer lengths are DWORDs, but the
wrappers declared them as int64. Media Foundation wrote four bytes into
eight-byte fields, which only worked because the upper bytes started
zero and stayed zero. Lock&#39;s parameters were also named backwards: the
second output is the maximum length and the third the current length.

</content>
</entry>
<entry>
<id>ca92fe50f56e07bb9c6cf1b85ef8f3bb2a9411df</id>
<published>2026-09-17T01:26:02Z</published>
<updated>2026-09-17T16:11:13Z</updated>
<title type="text">audio: gofmt doc comments</title>
<link rel="alternate" type="text/html" href="commit/ca92fe50f56e07bb9c6cf1b85ef8f3bb2a9411df.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit ca92fe50f56e07bb9c6cf1b85ef8f3bb2a9411df
parent 075de28390e236d09e8640665574fc8060d3bc77
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:26:02 -0400

audio: gofmt doc comments

Go 1.19 gofmt reformats indented code blocks in doc comments to a single
tab. No code changes; this keeps `gofmt -l` quiet before the fixes that
follow.

</content>
</entry>
<entry>
<id>075de28390e236d09e8640665574fc8060d3bc77</id>
<published>2026-09-17T01:25:30Z</published>
<updated>2026-09-17T16:11:13Z</updated>
<title type="text">audio: exclude Windows from the ffmpeg fallback build constraint</title>
<link rel="alternate" type="text/html" href="commit/075de28390e236d09e8640665574fc8060d3bc77.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 075de28390e236d09e8640665574fc8060d3bc77
parent bf384e6e4d66b1db0f82ac9dd046dcf962b00181
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Wed, 16 Sep 2026 21:25:30 -0400

audio: exclude Windows from the ffmpeg fallback build constraint

The Windows implementation became pure Go and lost its cgo requirement,
but the fallback file still activated on !cgo for every OS. Building on
Windows with CGO_ENABLED=0 therefore compiled both files and failed on
duplicate declarations of play, load, decode, start and end.

</content>
</entry>
<entry>
<id>bf384e6e4d66b1db0f82ac9dd046dcf962b00181</id>
<published>2025-06-14T21:20:51Z</published>
<updated>2025-06-14T21:20:51Z</updated>
<title type="text">ci: mirror to github</title>
<link rel="alternate" type="text/html" href="commit/bf384e6e4d66b1db0f82ac9dd046dcf962b00181.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit bf384e6e4d66b1db0f82ac9dd046dcf962b00181
parent fd00e3385aa0cb4b09b64e17af905687ecaccb5b
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Sat, 14 Jun 2025 18:20:51 -0300

ci: mirror to github

</content>
</entry>
<entry>
<id>fd00e3385aa0cb4b09b64e17af905687ecaccb5b</id>
<published>2024-05-06T05:58:37Z</published>
<updated>2024-05-06T05:58:37Z</updated>
<title type="text">nativeaudio: [macos] document packetsPerLoop</title>
<link rel="alternate" type="text/html" href="commit/fd00e3385aa0cb4b09b64e17af905687ecaccb5b.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit fd00e3385aa0cb4b09b64e17af905687ecaccb5b
parent 38c008f470c4d41f8258132ba6fe20d027813787
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon,  6 May 2024 13:58:37 +0800

nativeaudio: [macos] document packetsPerLoop

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>38c008f470c4d41f8258132ba6fe20d027813787</id>
<published>2024-05-06T05:17:45Z</published>
<updated>2024-05-06T05:17:45Z</updated>
<title type="text">nativeaudio: update package doc</title>
<link rel="alternate" type="text/html" href="commit/38c008f470c4d41f8258132ba6fe20d027813787.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 38c008f470c4d41f8258132ba6fe20d027813787
parent 918a97d444b7e80953afbdef4490a47691342b1b
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon,  6 May 2024 13:17:45 +0800

nativeaudio: update package doc

</content>
</entry>
<entry>
<id>918a97d444b7e80953afbdef4490a47691342b1b</id>
<published>2024-05-06T05:16:25Z</published>
<updated>2024-05-06T05:16:25Z</updated>
<title type="text">test: use builtin &#39;min&#39;</title>
<link rel="alternate" type="text/html" href="commit/918a97d444b7e80953afbdef4490a47691342b1b.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 918a97d444b7e80953afbdef4490a47691342b1b
parent 8b84f1e37cbdfefceb2f808f235ee1b1932f7e13
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon,  6 May 2024 13:16:25 +0800

test: use builtin &#39;min&#39;

No need for user level function anymore.

</content>
</entry>
<entry>
<id>8b84f1e37cbdfefceb2f808f235ee1b1932f7e13</id>
<published>2024-05-06T05:14:57Z</published>
<updated>2024-05-06T05:14:57Z</updated>
<title type="text">test: benchmark decode against decode</title>
<link rel="alternate" type="text/html" href="commit/8b84f1e37cbdfefceb2f808f235ee1b1932f7e13.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 8b84f1e37cbdfefceb2f808f235ee1b1932f7e13
parent 3126dcc8bb9d5422d1bb90975ac345d331016ce2
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon,  6 May 2024 13:14:57 +0800

test: benchmark decode against decode

No point comparing a load to a decode.

</content>
</entry>
<entry>
<id>3126dcc8bb9d5422d1bb90975ac345d331016ce2</id>
<published>2024-05-06T04:57:14Z</published>
<updated>2024-05-06T05:00:34Z</updated>
<title type="text">nativeaudio: [macos] documentation</title>
<link rel="alternate" type="text/html" href="commit/3126dcc8bb9d5422d1bb90975ac345d331016ce2.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 3126dcc8bb9d5422d1bb90975ac345d331016ce2
parent 6e52f056479261978e986550df81c90d31ba14dc
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon,  6 May 2024 12:57:14 +0800

nativeaudio: [macos] documentation

Aid readability by documenting somes edges.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>6e52f056479261978e986550df81c90d31ba14dc</id>
<published>2024-05-03T13:15:10Z</published>
<updated>2024-05-03T13:15:10Z</updated>
<title type="text">nativeaudio: [macos] fix buffering bug</title>
<link rel="alternate" type="text/html" href="commit/6e52f056479261978e986550df81c90d31ba14dc.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 6e52f056479261978e986550df81c90d31ba14dc
parent e9d2b0fd1b9796d1ecd771fa3384428c49d4d933
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  3 May 2024 21:15:10 +0800

nativeaudio: [macos] fix buffering bug

We need to have the number of bytes read correctly updated.

</content>
</entry>
<entry>
<id>e9d2b0fd1b9796d1ecd771fa3384428c49d4d933</id>
<published>2024-05-03T09:09:22Z</published>
<updated>2024-05-03T09:09:22Z</updated>
<title type="text">nativeaudio: update readme</title>
<link rel="alternate" type="text/html" href="commit/e9d2b0fd1b9796d1ecd771fa3384428c49d4d933.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit e9d2b0fd1b9796d1ecd771fa3384428c49d4d933
parent b99d4924dc35ce789e97cfb932a4f146377061ce
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  3 May 2024 17:09:22 +0800

nativeaudio: update readme

We have macOS support, yay!

</content>
</entry>
<entry>
<id>b99d4924dc35ce789e97cfb932a4f146377061ce</id>
<published>2024-05-03T08:51:50Z</published>
<updated>2024-05-03T08:52:41Z</updated>
<title type="text">nativeaudio: [macos] allow requested bytes to exceed audio data</title>
<link rel="alternate" type="text/html" href="commit/b99d4924dc35ce789e97cfb932a4f146377061ce.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit b99d4924dc35ce789e97cfb932a4f146377061ce
parent 578749db237b7d4e186be0d9267ffde33a46e080
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  3 May 2024 16:51:50 +0800

nativeaudio: [macos] allow requested bytes to exceed audio data

A lovely undocumented feature of this api. It seems like we need to
handle the caller asking for more than we have.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>578749db237b7d4e186be0d9267ffde33a46e080</id>
<published>2024-05-03T08:20:01Z</published>
<updated>2024-05-03T08:20:01Z</updated>
<title type="text">test: add macos native golden output</title>
<link rel="alternate" type="text/html" href="commit/578749db237b7d4e186be0d9267ffde33a46e080.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 578749db237b7d4e186be0d9267ffde33a46e080
parent b5d777e24d900661857614bfae7096190a26ef88
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  3 May 2024 16:20:01 +0800

test: add macos native golden output

There appears to be significant differences in output between the
uncompressed data from CoreAudio vs Windows MediaFoundation. To keep the
test passing, we can supply a golden output that was computed from
CoreAudio instead.

</content>
</entry>
<entry>
<id>b5d777e24d900661857614bfae7096190a26ef88</id>
<published>2024-05-03T08:18:32Z</published>
<updated>2024-05-03T08:18:32Z</updated>
<title type="text">cmd/nativeaudio: allow conversion</title>
<link rel="alternate" type="text/html" href="commit/b5d777e24d900661857614bfae7096190a26ef88.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit b5d777e24d900661857614bfae7096190a26ef88
parent 510674d8bb8e294f99a0f1e4550f67abeb78647a
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  3 May 2024 16:18:32 +0800

cmd/nativeaudio: allow conversion

Convert the audio file instead of playing it, if out is specified.

</content>
</entry>
<entry>
<id>510674d8bb8e294f99a0f1e4550f67abeb78647a</id>
<published>2024-05-03T05:26:49Z</published>
<updated>2024-05-03T05:27:52Z</updated>
<title type="text">nativeaudio: test harness for memory leaks</title>
<link rel="alternate" type="text/html" href="commit/510674d8bb8e294f99a0f1e4550f67abeb78647a.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 510674d8bb8e294f99a0f1e4550f67abeb78647a
parent b654445175fea5e719d2d00636bac17f70e1e82b
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  3 May 2024 13:26:49 +0800

nativeaudio: test harness for memory leaks

This test verifies expectations about the heap after the decode is
performed.

</content>
</entry>
<entry>
<id>b654445175fea5e719d2d00636bac17f70e1e82b</id>
<published>2024-05-02T07:08:24Z</published>
<updated>2024-05-03T05:27:50Z</updated>
<title type="text">nativeaudio: [macos] native implementation</title>
<link rel="alternate" type="text/html" href="commit/b654445175fea5e719d2d00636bac17f70e1e82b.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit b654445175fea5e719d2d00636bac17f70e1e82b
parent 8cded971ac79011745b25cb8a0dd66fa4f05b87b
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu,  2 May 2024 15:08:24 +0800

nativeaudio: [macos] native implementation

This commit implements audio decoding using AudioToolbox and
AVFoundation.

</content>
</entry>
<entry>
<id>8cded971ac79011745b25cb8a0dd66fa4f05b87b</id>
<published>2024-05-02T07:03:52Z</published>
<updated>2024-05-02T07:03:52Z</updated>
<title type="text">go.*: update deps</title>
<link rel="alternate" type="text/html" href="commit/8cded971ac79011745b25cb8a0dd66fa4f05b87b.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 8cded971ac79011745b25cb8a0dd66fa4f05b87b
parent 52b0dafe866ca18b9f2f8f92e27ef91646c028e2
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu,  2 May 2024 15:03:52 +0800

go.*: update deps

</content>
</entry>
<entry>
<id>52b0dafe866ca18b9f2f8f92e27ef91646c028e2</id>
<published>2024-03-04T20:51:20Z</published>
<updated>2024-03-04T20:51:20Z</updated>
<title type="text">audio: [Windows] return init error at runtime</title>
<link rel="alternate" type="text/html" href="commit/52b0dafe866ca18b9f2f8f92e27ef91646c028e2.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 52b0dafe866ca18b9f2f8f92e27ef91646c028e2
parent 7cc149941bfb12c0c82dddc7b63d1bbaae515ce4
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue,  5 Mar 2024 04:51:20 +0800

audio: [Windows] return init error at runtime

For platforms that don&#39;t have MediaFoundation we can avoid panicking by
returning the error when Start is called.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>7cc149941bfb12c0c82dddc7b63d1bbaae515ce4</id>
<published>2024-01-05T10:25:01Z</published>
<updated>2024-01-05T10:28:41Z</updated>
<title type="text">nativeaudio: [Windows] pure Go implementation</title>
<link rel="alternate" type="text/html" href="commit/7cc149941bfb12c0c82dddc7b63d1bbaae515ce4.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 7cc149941bfb12c0c82dddc7b63d1bbaae515ce4
parent 54d36e7969249bef53db07591ffd595cc19bcd05
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  5 Jan 2024 18:25:01 +0800

nativeaudio: [Windows] pure Go implementation

This commits orchestrates Windows Media Foundation using COM directly in
Go - no CGO needed.

This means Windows is now an easy cross compile target from any other
platform.

This version is more efficient because it avoids copying the data into
the Media Foundation and has less bugs. It also enables hardware
acceleration.

Playback has been changed to use oto instead of a different code tree
dedicated to direct playback: it&#39;s less code to manage.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>54d36e7969249bef53db07591ffd595cc19bcd05</id>
<published>2024-01-05T10:23:20Z</published>
<updated>2024-01-05T10:23:47Z</updated>
<title type="text">internal: TriggerReader</title>
<link rel="alternate" type="text/html" href="commit/54d36e7969249bef53db07591ffd595cc19bcd05.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 54d36e7969249bef53db07591ffd595cc19bcd05
parent 8b40d468a0c715b6d0ad4b18fa6b6e6bbb531d78
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  5 Jan 2024 18:23:20 +0800

internal: TriggerReader

This type triggers a callback when it&#39;s internal Reader hits EOF.

This is useful with ebitengine/oto/v3 because it doesn&#39;t provide a nice
way to detect end of playback.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>8b40d468a0c715b6d0ad4b18fa6b6e6bbb531d78</id>
<published>2024-01-05T10:22:45Z</published>
<updated>2024-01-05T10:22:45Z</updated>
<title type="text">cmd/nativeaudio: simple command for playing audio files directly</title>
<link rel="alternate" type="text/html" href="commit/8b40d468a0c715b6d0ad4b18fa6b6e6bbb531d78.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 8b40d468a0c715b6d0ad4b18fa6b6e6bbb531d78
parent b3e9ecc819164f8243e012563dedbe6368801801
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri,  5 Jan 2024 18:22:45 +0800

cmd/nativeaudio: simple command for playing audio files directly

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>b3e9ecc819164f8243e012563dedbe6368801801</id>
<published>2024-01-03T22:25:03Z</published>
<updated>2024-01-03T22:25:03Z</updated>
<title type="text">audio: [Windows] move some code into Go space</title>
<link rel="alternate" type="text/html" href="commit/b3e9ecc819164f8243e012563dedbe6368801801.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit b3e9ecc819164f8243e012563dedbe6368801801
parent 2c4a24aed38e2aa94732cde2cb10905f600a18be
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu,  4 Jan 2024 06:25:03 +0800

audio: [Windows] move some code into Go space

- structured error type that contains the error code
- call MFStartup and MFShutdown directly
- use modern unsafe facilities

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>2c4a24aed38e2aa94732cde2cb10905f600a18be</id>
<published>2024-01-03T22:24:43Z</published>
<updated>2024-01-03T22:24:43Z</updated>
<title type="text">mod: use go 1.21</title>
<link rel="alternate" type="text/html" href="commit/2c4a24aed38e2aa94732cde2cb10905f600a18be.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 2c4a24aed38e2aa94732cde2cb10905f600a18be
parent 5864a159ea62ab86b284ab0d255d94213d5b3d01
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu,  4 Jan 2024 06:24:43 +0800

mod: use go 1.21

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>5864a159ea62ab86b284ab0d255d94213d5b3d01</id>
<published>2024-01-03T22:22:32Z</published>
<updated>2024-01-03T22:22:32Z</updated>
<title type="text">remove extraneous C code</title>
<link rel="alternate" type="text/html" href="commit/5864a159ea62ab86b284ab0d255d94213d5b3d01.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 5864a159ea62ab86b284ab0d255d94213d5b3d01
parent 834c5174b806191e83cf4c7fcf8d72ce8a86c680
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu,  4 Jan 2024 06:22:32 +0800

remove extraneous C code

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>834c5174b806191e83cf4c7fcf8d72ce8a86c680</id>
<published>2023-10-23T00:49:09Z</published>
<updated>2023-10-23T00:51:25Z</updated>
<title type="text">test: expect error for corrupt data</title>
<link rel="alternate" type="text/html" href="commit/834c5174b806191e83cf4c7fcf8d72ce8a86c680.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 834c5174b806191e83cf4c7fcf8d72ce8a86c680
parent 4ac2f1f7ae4d7b0f02ceb52b15f9b5d1c724a7c4
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 23 Oct 2023 08:49:09 +0800

test: expect error for corrupt data

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>4ac2f1f7ae4d7b0f02ceb52b15f9b5d1c724a7c4</id>
<published>2023-10-23T00:46:40Z</published>
<updated>2023-10-23T00:46:40Z</updated>
<title type="text">windows: fix memory leak</title>
<link rel="alternate" type="text/html" href="commit/4ac2f1f7ae4d7b0f02ceb52b15f9b5d1c724a7c4.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 4ac2f1f7ae4d7b0f02ceb52b15f9b5d1c724a7c4
parent 2fb440b183ccd78f46e865faca1504d45d6d09d0
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 23 Oct 2023 08:46:40 +0800

windows: fix memory leak

We need to free the data which is allocated on the C heap returned from
C.CBytes function.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>2fb440b183ccd78f46e865faca1504d45d6d09d0</id>
<published>2023-10-23T00:44:30Z</published>
<updated>2023-10-23T00:44:30Z</updated>
<title type="text">windows: declare all types at top of function</title>
<link rel="alternate" type="text/html" href="commit/2fb440b183ccd78f46e865faca1504d45d6d09d0.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 2fb440b183ccd78f46e865faca1504d45d6d09d0
parent 2e9921f9bc54ac2034521aa2758555dfd621c6c7
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 23 Oct 2023 08:44:30 +0800

windows: declare all types at top of function

This fixes segfault condition on error. If we goto the done label before
these types are declared and initialized, we get a segfault.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>2e9921f9bc54ac2034521aa2758555dfd621c6c7</id>
<published>2023-10-23T00:43:18Z</published>
<updated>2023-10-23T00:43:18Z</updated>
<title type="text">ffmpeg: combine stdout and stderr</title>
<link rel="alternate" type="text/html" href="commit/2e9921f9bc54ac2034521aa2758555dfd621c6c7.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 2e9921f9bc54ac2034521aa2758555dfd621c6c7
parent 5a620efc525d83480f48978f91da004c633f5d7d
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 23 Oct 2023 08:43:18 +0800

ffmpeg: combine stdout and stderr

Stderr doesn&#39;t contain useful information, but stdout does.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>5a620efc525d83480f48978f91da004c633f5d7d</id>
<published>2023-05-19T08:04:23Z</published>
<updated>2023-05-19T08:04:23Z</updated>
<title type="text">audio_windows: fix leaked buffer</title>
<link rel="alternate" type="text/html" href="commit/5a620efc525d83480f48978f91da004c633f5d7d.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 5a620efc525d83480f48978f91da004c633f5d7d
parent 72294cf3e6c96db75249b3973b156c70786c51fe
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 19 May 2023 16:04:23 +0800

audio_windows: fix leaked buffer

This leak was caused by allocating the Buffer by the caller and the
within the callee, where the callee ignores the buffer provided to it
by the caller, and allocates it&#39;s own which it writes to the out pointer.

This lead to 1MB of leaked memory per invocation.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>72294cf3e6c96db75249b3973b156c70786c51fe</id>
<published>2023-05-19T07:49:40Z</published>
<updated>2023-05-19T07:49:40Z</updated>
<title type="text">main_test: remove unused function</title>
<link rel="alternate" type="text/html" href="commit/72294cf3e6c96db75249b3973b156c70786c51fe.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 72294cf3e6c96db75249b3973b156c70786c51fe
parent 1144afd26a8da8c00ab831be1c7f0628ca863586
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 19 May 2023 15:49:40 +0800

main_test: remove unused function

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>1144afd26a8da8c00ab831be1c7f0628ca863586</id>
<published>2023-05-18T13:10:15Z</published>
<updated>2023-05-18T13:10:15Z</updated>
<title type="text">audio_windows.c: fixed several memory leaks</title>
<link rel="alternate" type="text/html" href="commit/1144afd26a8da8c00ab831be1c7f0628ca863586.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 1144afd26a8da8c00ab831be1c7f0628ca863586
parent 78c8ffd8542e3f09b6cf37164aa536dd12f6bda9
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 18 May 2023 21:10:15 +0800

audio_windows.c: fixed several memory leaks

A few objects weren&#39;t being released correctly. This commits ensures
they are. There appears to be some more leak, but this change drastically
reduces the leak severity.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>78c8ffd8542e3f09b6cf37164aa536dd12f6bda9</id>
<published>2023-05-18T12:38:54Z</published>
<updated>2023-05-18T12:38:54Z</updated>
<title type="text">test: add test files that exercise C code in various ways</title>
<link rel="alternate" type="text/html" href="commit/78c8ffd8542e3f09b6cf37164aa536dd12f6bda9.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 78c8ffd8542e3f09b6cf37164aa536dd12f6bda9
parent 35931843c2f9d6dd8d1c7e50e4fcd654df5dcde1
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 18 May 2023 20:38:54 +0800

test: add test files that exercise C code in various ways

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>35931843c2f9d6dd8d1c7e50e4fcd654df5dcde1</id>
<published>2023-05-18T05:16:12Z</published>
<updated>2023-05-18T05:16:12Z</updated>
<title type="text">Merge commit &#39;2717ef88f823bb149b803ef530c22d48202f9f94&#39; as &#39;vendor/growable-buf&#39;</title>
<link rel="alternate" type="text/html" href="commit/35931843c2f9d6dd8d1c7e50e4fcd654df5dcde1.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 35931843c2f9d6dd8d1c7e50e4fcd654df5dcde1
parent 1c44b1ad59b8a59f377a2d7397b62bde4269dc80
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 18 May 2023 13:16:12 +0800

Merge commit &#39;2717ef88f823bb149b803ef530c22d48202f9f94&#39; as &#39;vendor/growable-buf&#39;

</content>
</entry>
<entry>
<id>2717ef88f823bb149b803ef530c22d48202f9f94</id>
<published>2023-05-18T05:16:12Z</published>
<updated>2023-05-18T05:16:12Z</updated>
<title type="text">Squashed &#39;vendor/growable-buf/&#39; content from commit 6ad7b3d</title>
<link rel="alternate" type="text/html" href="commit/2717ef88f823bb149b803ef530c22d48202f9f94.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 2717ef88f823bb149b803ef530c22d48202f9f94
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 18 May 2023 13:16:12 +0800

Squashed &#39;vendor/growable-buf/&#39; content from commit 6ad7b3d

git-subtree-dir: vendor/growable-buf
git-subtree-split: 6ad7b3dcc1f22edb79e0e33be0e79c17859febff

</content>
</entry>
<entry>
<id>1c44b1ad59b8a59f377a2d7397b62bde4269dc80</id>
<published>2022-05-09T09:31:06Z</published>
<updated>2022-05-09T09:31:06Z</updated>
<title type="text">audio_ffmpeg: threadsafe decoding</title>
<link rel="alternate" type="text/html" href="commit/1c44b1ad59b8a59f377a2d7397b62bde4269dc80.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 1c44b1ad59b8a59f377a2d7397b62bde4269dc80
parent 7a22adb29e362e75cfb59bf41eb933daa9df1b11
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon,  9 May 2022 17:31:06 +0800

audio_ffmpeg: threadsafe decoding

Uniquely identify each tmp file so that multiple threads
trying to decode don&#39;t race.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>7a22adb29e362e75cfb59bf41eb933daa9df1b11</id>
<published>2022-02-02T20:57:13Z</published>
<updated>2022-02-02T20:57:13Z</updated>
<title type="text">nativeaudio: use lower-case paths to simplify cross-compilation</title>
<link rel="alternate" type="text/html" href="commit/7a22adb29e362e75cfb59bf41eb933daa9df1b11.html" />
<author>
<name>Chris Waldon</name>
<email>christopher.waldon.dev@gmail.com</email>
</author>
<content type="text">commit 7a22adb29e362e75cfb59bf41eb933daa9df1b11
parent a7cb7b67a124ad75e4d085bb5a2f11c2bc47b79a
Author: Chris Waldon &lt;christopher.waldon.dev@gmail.com&gt;
Date:   Wed,  2 Feb 2022 15:57:13 -0500

nativeaudio: use lower-case paths to simplify cross-compilation

Windows paths are not case-sensitive, but Linux paths are. Linux cross-compilers
install the windows headers and libraries in all-lower-case, which fails to build
if any of them contain upper-case letters.

Signed-off-by: Chris Waldon &lt;christopher.waldon.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>a7cb7b67a124ad75e4d085bb5a2f11c2bc47b79a</id>
<published>2021-10-28T08:04:39Z</published>
<updated>2021-10-28T08:04:39Z</updated>
<title type="text">internal/test: use royalty free audio sample</title>
<link rel="alternate" type="text/html" href="commit/a7cb7b67a124ad75e4d085bb5a2f11c2bc47b79a.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit a7cb7b67a124ad75e4d085bb5a2f11c2bc47b79a
parent 93b6bd5db16d6b83c262b16505b9626d65444c37
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 28 Oct 2021 16:04:39 +0800

internal/test: use royalty free audio sample

mixkit-game-level-music-698.wav

https://assets.mixkit.co/sfx/download/mixkit-game-level-music-689.wav

- original file is kept as is
- compressed.m4a is that file compressed
- uncompressed variants are the raw pcm of uncompressing the m4a

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>93b6bd5db16d6b83c262b16505b9626d65444c37</id>
<published>2021-10-28T05:17:13Z</published>
<updated>2021-10-28T05:30:14Z</updated>
<title type="text">nativeaudio: [ffmpeg] probe to get format details</title>
<link rel="alternate" type="text/html" href="commit/93b6bd5db16d6b83c262b16505b9626d65444c37.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 93b6bd5db16d6b83c262b16505b9626d65444c37
parent 660c4fdaaf824a7313ea60956580fa02d69f7b11
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 28 Oct 2021 13:17:13 +0800

nativeaudio: [ffmpeg] probe to get format details

This should fix platforms that rely on ffmpeg by outputting the correct
format details namely sample rate and channels. Bit depth is known
ahead of time because we specify s16le which is 16bit/2byte per sample.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>660c4fdaaf824a7313ea60956580fa02d69f7b11</id>
<published>2021-10-28T04:05:11Z</published>
<updated>2021-10-28T04:05:11Z</updated>
<title type="text">nativeaudio: [docs] update readme</title>
<link rel="alternate" type="text/html" href="commit/660c4fdaaf824a7313ea60956580fa02d69f7b11.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 660c4fdaaf824a7313ea60956580fa02d69f7b11
parent 837631ba1992643872d6acd65851f16d9765eaae
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 28 Oct 2021 12:05:11 +0800

nativeaudio: [docs] update readme

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>837631ba1992643872d6acd65851f16d9765eaae</id>
<published>2021-10-28T04:00:11Z</published>
<updated>2021-10-28T04:00:11Z</updated>
<title type="text">nativeaudio: [unknown] shell out to ffmpeg</title>
<link rel="alternate" type="text/html" href="commit/837631ba1992643872d6acd65851f16d9765eaae.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 837631ba1992643872d6acd65851f16d9765eaae
parent 6fb83b0f1a73c83454d8583d9bede6c0cf5e7dd7
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 28 Oct 2021 12:00:11 +0800

nativeaudio: [unknown] shell out to ffmpeg

For platforms we haven&#39;t explicitly handled, shell out to ffmpeg.
If the system is handled but cgo is disabled, also use ffmpeg.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>6fb83b0f1a73c83454d8583d9bede6c0cf5e7dd7</id>
<published>2021-10-28T03:53:02Z</published>
<updated>2021-10-28T03:53:02Z</updated>
<title type="text">nativeaudio: [macos,linux] add lifecycle stubs</title>
<link rel="alternate" type="text/html" href="commit/6fb83b0f1a73c83454d8583d9bede6c0cf5e7dd7.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 6fb83b0f1a73c83454d8583d9bede6c0cf5e7dd7
parent 894cde591b3a1b6729a5384b9b70475198023772
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 28 Oct 2021 11:53:02 +0800

nativeaudio: [macos,linux] add lifecycle stubs

Make sure we actually compile on these platforms!

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>894cde591b3a1b6729a5384b9b70475198023772</id>
<published>2021-10-28T03:42:00Z</published>
<updated>2021-10-28T03:42:00Z</updated>
<title type="text">nativeaudio: [macos] actually compile</title>
<link rel="alternate" type="text/html" href="commit/894cde591b3a1b6729a5384b9b70475198023772.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 894cde591b3a1b6729a5384b9b70475198023772
parent 895b3a29c5b382f53ee26494676d7b93f7579cdc
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Thu, 28 Oct 2021 11:42:00 +0800

nativeaudio: [macos] actually compile

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>895b3a29c5b382f53ee26494676d7b93f7579cdc</id>
<published>2021-10-26T13:55:00Z</published>
<updated>2021-10-26T13:55:00Z</updated>
<title type="text">example: small example showcasing api</title>
<link rel="alternate" type="text/html" href="commit/895b3a29c5b382f53ee26494676d7b93f7579cdc.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 895b3a29c5b382f53ee26494676d7b93f7579cdc
parent 10025629ef7bfecd4b0a0ed827d5390fddeac520
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 21:55:00 +0800

example: small example showcasing api

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>10025629ef7bfecd4b0a0ed827d5390fddeac520</id>
<published>2021-10-26T13:53:09Z</published>
<updated>2021-10-26T13:53:09Z</updated>
<title type="text">nativeaudio: use built-in helpers at the cgo boundary</title>
<link rel="alternate" type="text/html" href="commit/10025629ef7bfecd4b0a0ed827d5390fddeac520.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 10025629ef7bfecd4b0a0ed827d5390fddeac520
parent 7981a03eda14412c644a71b4cd9820fb5d097584
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 21:53:09 +0800

nativeaudio: use built-in helpers at the cgo boundary

The performance gain is negligible so we shall prefer correctness.

BEFORE

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12               165           7272938 ns/op              88 B/op          3 allocs/op
BenchmarkDecode/native-decode-12             164           7075614 ns/op              72 B/op          2 allocs/op
BenchmarkDecode/ffmpeg-load-12                19          61365137 ns/op         2262458 B/op       1423 allocs/op

AFTER

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12               165           7371150 ns/op          606245 B/op          3 allocs/op
BenchmarkDecode/native-decode-12             159           7471619 ns/op          606250 B/op          3 allocs/op
BenchmarkDecode/ffmpeg-load-12                19          61339426 ns/op         2262489 B/op       1423 allocs/op

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>7981a03eda14412c644a71b4cd9820fb5d097584</id>
<published>2021-10-26T13:46:06Z</published>
<updated>2021-10-26T13:48:02Z</updated>
<title type="text">nativeaudio: [perf] init media framework exactly once</title>
<link rel="alternate" type="text/html" href="commit/7981a03eda14412c644a71b4cd9820fb5d097584.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 7981a03eda14412c644a71b4cd9820fb5d097584
parent e99fa2291ea8951e4b5524ebabf95504533c44b5
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 21:46:06 +0800

nativeaudio: [perf] init media framework exactly once

Turns out, initializing the media framework every call was VERY
expensive. By introducing startup/shutdown semantics we reduce ns/op
by 2 orders of magnitude.

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12               165           7272938 ns/op              88 B/op          3 allocs/op
BenchmarkDecode/native-decode-12             164           7075614 ns/op              72 B/op          2 allocs/op
BenchmarkDecode/ffmpeg-load-12                19          61365137 ns/op         2262458 B/op       1423 allocs/op

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>e99fa2291ea8951e4b5524ebabf95504533c44b5</id>
<published>2021-10-26T09:50:00Z</published>
<updated>2021-10-26T09:50:00Z</updated>
<title type="text">nativeaudio: [windows] avoid copying buffer out from C</title>
<link rel="alternate" type="text/html" href="commit/e99fa2291ea8951e4b5524ebabf95504533c44b5.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit e99fa2291ea8951e4b5524ebabf95504533c44b5
parent e68bad3f1f3680f47dbc02c63f7d0242787a16a9
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 17:50:00 +0800

nativeaudio: [windows] avoid copying buffer out from C

We can still free the memory inside a finalizer (I think) when the GC
decides to free it.

That way we can use the C memory, without copying anything and the
caller can treat it like a standard slice in the meantime.

This lets us avoid allocating memory back out of C, without needing to
go all the way and manage the buffer from Go (which is still on the
cards because it gives Go more control - but not now!).

In the benchmark, you&#39;ll notice that Go side only allocates 72b total;
I think the finalizer closure escapes to the heap.

The other 16b are for the CString allocation containing the file path
in nativeaudio.Load.

Unfortunately this optimization is, again, negiligible in terms of ns/op
because the heavy lifting is the audio decoding.

I don&#39;t like that native is 6x more expensive than shelling out to
ffmpeg. Could simply be my amateur C code, OR Windows Media Foundation
is just that bad.

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12         	       4	 317390725 ns/op	      88 B/op	       3 allocs/op
BenchmarkDecode/native-decode-12       	       4	 269792350 ns/op	      72 B/op	       2 allocs/op
BenchmarkDecode/ffmpeg-load-12         	      19	  61750084 ns/op	 2279866 B/op	    1498 allocs/op

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>e68bad3f1f3680f47dbc02c63f7d0242787a16a9</id>
<published>2021-10-26T09:03:26Z</published>
<updated>2021-10-26T09:03:26Z</updated>
<title type="text">nativeaudio: [windows] remote debug symbols by default</title>
<link rel="alternate" type="text/html" href="commit/e68bad3f1f3680f47dbc02c63f7d0242787a16a9.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit e68bad3f1f3680f47dbc02c63f7d0242787a16a9
parent 8a39e04d75ff38b156b0817f64a8f1f767ad1caf
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 17:03:26 +0800

nativeaudio: [windows] remote debug symbols by default

Leave note for future reference when debugging is required.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>8a39e04d75ff38b156b0817f64a8f1f767ad1caf</id>
<published>2021-10-26T08:57:36Z</published>
<updated>2021-10-26T08:57:36Z</updated>
<title type="text">nativeaudio: [windows] avoid buffer allocating calling into C</title>
<link rel="alternate" type="text/html" href="commit/8a39e04d75ff38b156b0817f64a8f1f767ad1caf.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 8a39e04d75ff38b156b0817f64a8f1f767ad1caf
parent 8e6998c8994381afcacf51d9a0fe6c6f8b101597
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 16:57:36 +0800

nativeaudio: [windows] avoid buffer allocating calling into C

We can pass the raw slice to C and avoid using C.CBytes which performs
an allocation.

Result is a very minor improvement, almost negligible but it&#39;s a trival
change so we can keep it.

BEFORE
======

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12         	       4	 311614425 ns/op	  606240 B/op	       3 allocs/op
BenchmarkDecode/native-decode-12       	       4	 263828450 ns/op	  606250 B/op	       3 allocs/op
BenchmarkDecode/ffmpeg-load-12         	      19	  59440921 ns/op	 2279943 B/op	    1498 allocs/op

AFTER
=====

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-load-12         	       4	 316714700 ns/op	  606240 B/op	       3 allocs/op
BenchmarkDecode/native-decode-12       	       4	 258123650 ns/op	  606226 B/op	       2 allocs/op
BenchmarkDecode/ffmpeg-load-12         	      19	  59983868 ns/op	 2279907 B/op	    1498 allocs/op

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>8e6998c8994381afcacf51d9a0fe6c6f8b101597</id>
<published>2021-10-26T08:46:01Z</published>
<updated>2021-10-26T08:46:01Z</updated>
<title type="text">nativeaudio: benchmark native decode against ffmpeg</title>
<link rel="alternate" type="text/html" href="commit/8e6998c8994381afcacf51d9a0fe6c6f8b101597.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 8e6998c8994381afcacf51d9a0fe6c6f8b101597
parent 666898492c80aabd1195ba8856066b0858b57189
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 16:46:01 +0800

nativeaudio: benchmark native decode against ffmpeg

Benchmark native load against ffmepg load. Unfortunately we have to go
through the filesystem because of deficiencies in FFmpegDecode (some
audio formats cannot be piped to ffmpeg).

goos: windows
goarch: amd64
pkg: git.sr.ht/~jackmordaunt/nativeaudio/internal/test
cpu: AMD Ryzen 5 3600 6-Core Processor
BenchmarkDecode/native-12         	       4	 318420150 ns/op	  606240 B/op	       3 allocs/op
BenchmarkDecode/ffmpeg-12         	      19	  61705947 ns/op	 2279976 B/op	    1498 allocs/op

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>666898492c80aabd1195ba8856066b0858b57189</id>
<published>2021-10-26T08:45:01Z</published>
<updated>2021-10-26T08:45:01Z</updated>
<title type="text">nativeaudio: introduce decode api to macos and linux</title>
<link rel="alternate" type="text/html" href="commit/666898492c80aabd1195ba8856066b0858b57189.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 666898492c80aabd1195ba8856066b0858b57189
parent d1e38c3868005fe442299772d84306c7960571f6
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 16:45:01 +0800

nativeaudio: introduce decode api to macos and linux

FFmpeg functions are exported because they are needed in the benchmarks.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>d1e38c3868005fe442299772d84306c7960571f6</id>
<published>2021-10-26T07:48:12Z</published>
<updated>2021-10-26T07:48:12Z</updated>
<title type="text">nativeaudio: [fix] free errors</title>
<link rel="alternate" type="text/html" href="commit/d1e38c3868005fe442299772d84306c7960571f6.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit d1e38c3868005fe442299772d84306c7960571f6
parent b94efcdfe4f3304c6ea9de1da665ef3e3ff3c29c
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 15:48:12 +0800

nativeaudio: [fix] free errors

ErrorFree was failing because it was trying to free `const * char`
string literals which were never dynamically allocated.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>b94efcdfe4f3304c6ea9de1da665ef3e3ff3c29c</id>
<published>2021-10-26T07:40:14Z</published>
<updated>2021-10-26T07:41:54Z</updated>
<title type="text">nativeaudio: correctly specify output format</title>
<link rel="alternate" type="text/html" href="commit/b94efcdfe4f3304c6ea9de1da665ef3e3ff3c29c.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit b94efcdfe4f3304c6ea9de1da665ef3e3ff3c29c
parent 6579c4ac6c3d5dfeab328ec59f36d4e9c13e9a69
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 15:40:14 +0800

nativeaudio: correctly specify output format

This patch does a big tidy alongside correctly specifying the output
format as PCM.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>6579c4ac6c3d5dfeab328ec59f36d4e9c13e9a69</id>
<published>2021-10-26T06:35:22Z</published>
<updated>2021-10-26T06:35:22Z</updated>
<title type="text">nativeaudio: report pcm format from load function</title>
<link rel="alternate" type="text/html" href="commit/6579c4ac6c3d5dfeab328ec59f36d4e9c13e9a69.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 6579c4ac6c3d5dfeab328ec59f36d4e9c13e9a69
parent b3d9551a31372069f565f83b35239a60662e66e8
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 14:35:22 +0800

nativeaudio: report pcm format from load function

Introduce a function for getting metadata from a stream which we can
use to populate a Format struct.

Furthermore Load relies on decode minor function, which means the
incorrect output of Decode major is specific to how it initializes
the stream reader.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>b3d9551a31372069f565f83b35239a60662e66e8</id>
<published>2021-10-26T05:47:23Z</published>
<updated>2021-10-26T05:47:23Z</updated>
<title type="text">nativeaudio: [wip] decode buffered bytes</title>
<link rel="alternate" type="text/html" href="commit/b3d9551a31372069f565f83b35239a60662e66e8.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit b3d9551a31372069f565f83b35239a60662e66e8
parent 08f125a1e34fc4d76e971f7132364b310bf09acd
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Tue, 26 Oct 2021 13:47:23 +0800

nativeaudio: [wip] decode buffered bytes

Decode function that should decode a byte buffer and return the
uncompressed PCM s16le with playback metadata.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>08f125a1e34fc4d76e971f7132364b310bf09acd</id>
<published>2021-10-24T19:15:58Z</published>
<updated>2021-10-24T19:26:43Z</updated>
<title type="text">nativeaudio: [fix] properly free dynamic errors</title>
<link rel="alternate" type="text/html" href="commit/08f125a1e34fc4d76e971f7132364b310bf09acd.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 08f125a1e34fc4d76e971f7132364b310bf09acd
parent 9e0bc636f05197087bd5e5b3c0b7de3cfb8d1e64
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Mon, 25 Oct 2021 03:15:58 +0800

nativeaudio: [fix] properly free dynamic errors

Walk the chain and deallocate as we go.

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
<entry>
<id>9e0bc636f05197087bd5e5b3c0b7de3cfb8d1e64</id>
<published>2021-10-22T15:29:38Z</published>
<updated>2021-10-22T15:29:38Z</updated>
<title type="text">nativeaudio: add project todos</title>
<link rel="alternate" type="text/html" href="commit/9e0bc636f05197087bd5e5b3c0b7de3cfb8d1e64.html" />
<author>
<name>Jack Mordaunt</name>
<email>jackmordaunt.dev@gmail.com</email>
</author>
<content type="text">commit 9e0bc636f05197087bd5e5b3c0b7de3cfb8d1e64
parent 86099c5d28e2fd11c72d1b4d08039b032ff2c7ed
Author: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;
Date:   Fri, 22 Oct 2021 23:29:38 +0800

nativeaudio: add project todos

Signed-off-by: Jack Mordaunt &lt;jackmordaunt.dev@gmail.com&gt;

</content>
</entry>
</feed>
