LoudPizza shenanigans
should be pretty easy to get a simple audio instance going, if you want to ask me make a thread
637 Replies
i made a thread
my tiny sample project will be accessible tomorrow
for now we have to just yolo
im assuming i should do a raw export of bad apple into stereo 16bit short data?
because you can only use bad apple for test songs
no other songs
the painful part about this is .NET's lack of audio libraries
don't mention NAudio or I'll shoot
ManagedBass is quite good, but not OSS
yeahhhhhh bit of a stretch really
when I want something OSS
feel free to port miniaudio to c# kekw
while i enjoy my LoudPizza
i prefer 32bit float
makes sense
i have yet to write a "AudioBufferInstance" class that transcode on the fly
oh OpenAL only supports 16bit signed integers
there is a flag for 32bit float
surely someone already did that right?
i doubt
it's literally a 3MB header file
it's hell
its an extension iirc, and i dont want to deal with extensions more than i already am having to given they are just borked
3MB header file
what
so much for being called "mini"
thats a perfectly reasonable size for an audio engine?
not all of that is going to be compiled, compiler wont put what isnt used
I hope we can just slap this to cppsharp and call it a day
yeah no LMAO
yeah it would've been TOO easy
it takes literally ages for any compiler to chew through it though
not having it in multiple headers also kills IDEs
audacity refuses to work so time to get some fork of audacity :^)
and the maintainer REFUSES to change it "bECAuase My SinGle HeaDEr"
gotta keep the "mini" moniker true 😛
audacity went to shit recently
they le fucking git made applying effects awful
you can't preview any part you want instantly
you need to select the whole thing and only do 5s of preview on the beginning
like what in the everliving fuck
time to heat my room compiling from source
keep in mind that the ogg streamer works
oh
👀
so if you got any ogg just slap it on VorbisReader
making badapple.ogg as we speak
its making a theora video god dAMN you ffmpeg
okay i went from mp4 -> mp3 -> ogg and it made an ACTUAL vorbis audio file
feel free to try setting up the async streamer yourself and come back if you struggle
(should be like 3 lines)
wake me up if someone makes a decent audio decoder library for C#
ffmpeg use any of the multiple shitty bindings
I don't want to die
create your own ffmpeg bindings, ez
ffmpeg bindings in silk when?
tried, no
shame
the bindings available are autogenerated from cppsharp
cppsharp
surely that must be limited to good old .net framework right
there is one ffmpeg bindings library that i like
am i on the right track
that is not the streamer but kinda yes otherwise
you can do vorbisReader.TotalSamples
and LoadRawWave is not what you want
at least not in the loop
HOLG SHIT
ITS DOING SOMETHIng
speed is wrong
the 2 ears are out of sync
BUT ITS DOING SOMETHING
let me record this shit
the right ear seems to be half way through the song
and the left ear right at the start
oddly
@grifon.petre would you happen to have experienced this when working with OpenAL?
and/or might have an idea of whats wrong
uh oh
this might be an incorrect pcm format
some pcm formats (crap ones) put the left channel first, and then the right channel
having said that usually the left channel will completely cut out before the right channel starts playing
I can't really hear the video, it's quiet and I'm on my phone, but this could either be an incorrect format, or incorrect output from the buffer
use reader.ReadSamples(span, reader.TotalSamples, reader.TotalSamples)
and new float[reader.TotalSamples * reader.Channels]
what is channelstride
o
that ReadSamples overload reads 11112222 instead of 12121212
yeah to me this sounds like incorrect translation from the buffer to openal
openal expects pcm data
[l, l, r, r]
AudioBuffer wants 11112222
i think loudpizza mixes into that
the actual vorbis is the poblem
YOOOOOO
it's the typical pcm format so it should
THAT WORKED
BAD APPLE
PLAYING
nice
time to listen to the entirety of bad apple for TESTING REASONS
tldr: NVorbis interleaved 11112222 into 12121212
eeeesh
so i just added an overload that gives me the raw data because loudpizza also likes raw data
what is it with things using crappy nonstandard pcm formats
it was a significant speedup
i vectorized the interleaving though 😉
i mean logically i can see why 1212121212 makes sense
don't even get me started with tracker files JEEZ
one chunk of [12][12][12] is a single 'metasample' of audio
like logically thats how i thought it was layed out
i didnt know it was 11112222
typical 16 bit pcm is
ehh 12121212 is good in streaming
11112222 is good for processing
[Left lower byte, Left upper byte, Right lower byte, Right upper byte]
which is what most things expectconclusion: both are useful
流れてく 時の中ででも 気だるさが ほらグルグル廻って
私から 離れる心も 見えないわ そう知らない?
oh i should make sure 3d audio works
after this loop of bad apple
first time I discovered bad apple was a Minecraft version like 6 years ago lmao
it was awesome tho, the actual video in Minecraft
if it's broken i blame openal lol
i know it will 95% chance of working, i just want to make bad apple spin around me in 3d audio
i hate youtube videos that say 8D but i can't seem to download any audiostream that actually has more than 2 channels >;(
i have a feeling i fucked up
holy shit I found it https://youtu.be/i1udDC-XLCQ
NiceMarkMC
YouTube
Bad Apple!! but it's in Minecraft Blocks
Bad Apple!! - a Touhou video recreated with Minecraft blocks and note blocks. I guess you could call it a Minecraft stop motion animation.
More information is available below! Read the full description :)
Note block song (+ song download) - https://www.youtube.com/watch?v=3Sf064dkVeY
* There are 6585 frames in this video, it runs at 30 frames...
its not doing anything
you need to enable 3d on the instance
and on the soloud handle
i think
i just switched from
play
to play3d
OH
update3dAudioITS BEAUTIFUL
it's so good that even the buttons are jamming
oh yeah rider just kinda
does that
it's the icon next to Debug disappearing isn't it
curseed
yup
that menu hasnt been updated to the new UI yet
so its buggy
@baebey if you plan to use loudpizza don't be afraid to message me about anything
makes sense
i'll be writing an SDL one next, then PR these sample apps in
how would i do async streaming by the way?
tldr:
and use
streamedStream
as an AudioInstance
(disposing StreamedAudioStream
automatically calls streamer.UnregisterStream
)wait i got this far how do i actually play it
oh right, StreamedAudioStream is an AudioSource not an AudioInstance
play wants an AudioSource
hol on
StreamedAudioStream is IAudioStream
i am clowning
create an
AudioStream audioSource = new(soloud, streamedStream);
i think i need to rename some types somehow
having IAudioStream
and AudioStream
is... confusingyou didn't initialize the nested VorbisReader
i have brain damage
i thought i had a better exception than a NRE for using an uninitialized VorbisReader 🙄
now its playing too slow
with slightly lower pitch
uhoh
i think theres a mismatch of sample rates
41000 vs 48000
code so far
weird, i thought i set the sample rate correctly
if you want i can send you the ogg file, and push my code so far to a repo
oh so i can build it? sure sure
cool one min and ill get a github repo up
GitHub
GitHub - Beyley/LoudPizza: Port of SoLoud for .NET
Port of SoLoud for .NET. Contribute to Beyley/LoudPizza development by creating an account on GitHub.
ogg file there
just clone it and run the
LoudPizza.Test
application'Could not find or load the native library: openal32.dllpanik
oh you can install the openal soft native package
i have it system-wide so i forgot
Silk.NET.OpenAL.Soft.Native
its possible its too old to have the extension though, in that case you will have to build from source
make sure you enable
soft
in the GetApi calls or it won't find the output dll from the nuget packageoh
so like
you are just setting sample rate to 48000 and channels to 2
and not reading what openal gives you
and you're not asking openal for specific sample rate or channels
oh do you have to?
... it gives you whatever it wants
aside from forgetting to pass the right format into BufferCallback i do give it a sample rate tho
not to mention that silk doesn't even expose the GetIntegerv enum for frequency or channels 🤔
only to BufferData, not when you open a device
... can you even ask openal for a specific samplerate
or is SoftCallbackBuffer a buffer that manages device rates
ugghhhh why is openal literally 7x worse than i remember it being
specification for the extension here https://openal-soft.org/openal-extensions/SOFT_callback_buffer.txt
"with <freq> being the base sample rate the samples will play at"
if it is an OpenAL problem, then its odd it works when i dont stream it
i hate openal i hate openal i hate openal
uhh no clue actually
are you sure you have to query that? the Silk WavePlayer example doesnt do that
it just reads the sample rate from the file and passes that directly into the buffer
i mean you don't have to
ugh, it plays at low pitch at 44100
sus
thats why im thinking LoudPizza is resampling it wrong, even if i tell OpenAL to play at 44100 it still is wrong
you are already telling the openal buffer what frequency your data is at, it's just an optimization for creating hardware device
yup, i'm investigating
found the problem i think
the buffer callback is trolling you
oh no?
numBytes is 3936 while the buffer size is 8192 bytes
and 3936 happens to not align on the 8192 buffer length
its ALMOST half the size
i dont understand why its doing that
because the buffer got set to pretty big so it requests often but not for full refills
i have a simple fix though i think
oh was
(int)(bufferSize * channels * sizeof(ushort))
too big?
i tried to match what i thought SDL was doingit's not too big
openal is just being clever
WHAT
SINCE WHEN
never
damn
it was all an elaborate L
same
If the return value is less than <numbytes>, it's treated as the end of the buffer and the source will play any complete samples before stopping.you are actually fucking kidding me
solution: always return numBytes
i refuse
but it w o r k s
if you call silence between buffer refills correct then sure!
what if return value is MORE than numbytes
does it just stab you
really hard
with a knife
.... it changed nothing
how bloody cursed
oh damn
i need to expose the actual scratch buffer size
why does openal take so god damn long to initialize anyways
is it slow? it didnt seem to be for me
111ms on my machine
idk, feels like seconds to me
yeah about 110ms on average for me, which isnt that bad
replace the init with that
oh shit i align a pointer in the wrong direction
thats not healthy
guess what
it quits immediately if you return less than numBytes
lmao chad
"oh you are done sending data, alright then DONE"
ok i am confused
what format does this take it in
because mixSigned16 outputs 12121212
5.3.4 seems to be about buffer content
https://www.openal.org/documentation/openal-1.1-specification.pdf
IT DOES WANT INTERLEAVED
121212121212
openal is weird
i hate it
Stereo data is expressed in an interleaved format, left channel sample followed by the right channel sample.
ok wait
i think everything is fine in soloud
hold the fuckety up
i am implementing SDL2 support as we speak to see
i'm just tired
SDL2 audio is godly compared to openshital
OpenShitAll
i am offended
Init is called as
Init()
btwmaybe try a rebuild?
because the interface definition is
uint channels = 2
ah
better than your old one which defaulted to 0 channels and that broke all the math
0 meant take platform default 🙃
there is a reason to calling
SoLoud.postinit_internal
oh i see thats an SDL thing
no, that's a backend thing
SDL just does that by default as well
i meant what is actually setting it from 0 to something else
SDL in the SDL backend
the desired vs obtained audio spec
yes, any other soloud backend should set it to something sane as well
i think its possible to get the highest supported one in OpenAL but i havent bothered :^)
i think i want to burn openal
valid
i also need to fix resampling apparently
alright i found the bug fuck
you did help in uncovering a new resampling bug though
sick
currently just finishing up the SDL2 backend
yup SDL2 provides the same behaviour, but importantly works
i need to revamp how audio instances work as a whole
this OOP shit is killing me
ECS time
based
i may go against my own and perksey's advice and use the silk sdl2 bindings here since it would let someone pass in their own get proc address function for whatever SDL2 binding they use
pull upstream for a fix btw
k
hold on
i forgot about the resampling bug
both backends work flawlessly with that commit
there, fixed the new bugger as well
also not to be annoying but i don't think i'll merge any PR from your fork
it would be too much code style cleanup 😅
fair, the code style of the rest of loudpizza is like night and day with mine lmao
it's a bit on me for not having a .editorconfig
i mean feel free to export one and ill try to match the rest best i can
but i can easily fix up code styles manually if i decide to merge
one thing about your original implementation is that it would break on net framework(im fairly certain)/mono(i think?) due to accessing instance fields from a native callback, which is why i use GCHandles no matter how much i hate them
sounds like you didn't leave the instance rooted?
but its not like its netstandard in the first place :^)
but yes, GCHandle good
i got no idea what that means, but i was yelled at by people for not using it in my video decoder FFmpeg callback since it would break on framework
rooting means having either a GC.KeepAlive so the object lives long enough in a method
or putting it in a field into another object that is alive
oh, thats not why i was yelled at, it was something about instance fields being just fucking cursed on framework in native callbacks
so it would not only break on netframework
... well then
i would rather not support that then :)
specifically instance fields when using
this
inside a native callback, no idea whyi rather not know the real issue, anyways
i'm going to bed
fair
oh you cant get an accurate exact timestamp, it seems to be updated infrequently hmm
ah i see, its only updated when you mix
i wonder if i can use a
Stopwatch
here to interpolate the values and get a much much more accurate valueok so like
what do you want to do
with stream time
because if you're getting the stream position, that will not practically be the current stream position
i want to know exactly what position in the song is playing
because mixing moves time
down to the milisecond
so every time your mix is called, record the current time stamp
and then do
currentTime - mixTimestamp + streamTimeBeforeMix
:yeehaw:ye im working on basically that rn
hmm
i have an idea
instead of tracking the time of every stream
nvm
wait
you can track the timestamp of a mix, and how much that mix mixed
and then do
streamTimeAfterMix - mixAmount
to get streamTimeBeforeMix
🧠
alright i think i ironed out every wrinkle in my brain for today
tldr: it's a solvable problemsolved
i got an interpolated time position working
but in the future, when i have a more ECS-based approach, i will probably have plenty of "events" (not c# events but fast ECS events) for implementing custom logic stuff
i basically track how long its been in real time since the last mix, then add that time to the last mix time
when the song is paused, i pause the time
hmm if you only wanted the soloud time and not the position of an individual stream then sure lmfao
it's just that pitch and stuff affects streams so uhh have fun 👍
i do it per voice
er the var is called voice but the actual class is AudioSourceInstance
each AudioSourceInstance stores its own time since the last mix
and i make sure that i take into account speed being different
i'm not merging that
yeah having 80 instances of stopwatch is dumb, but i wanted to see if it worked and it does, would just using
Stopwatch.GetTimestamp
be fine?
er wait no that wouldnt worki am on the other hand fine with implementing this myself some day
just keep your fork somewhat tidy so i can read it in a month lollllll
makes sense, feel free to not merge any of my stuff, im just modifying it to suit the needs of my engine
i try to keep commits mostly clean
forks good
(you committed Silk.NET.OpenAL.Extensions.Soft.dll into the repo lol)
thats because i use an extension i havent opened a PR for yet
ill be opening one soon
then once its merged the nuget will work fine
but why is it committed into the repo
to make your life easier when building it locally to test :^)
how dare you bloat my git objects
i can just remove the commit from the history
i know enough git-fu
good because git-fu kicked my ass earlier
The Modern Coder
YouTube
Learn how to rewrite Git history - Amend, Reword, Delete, Reorder, ...
In this video I'll dive into some of the ways Git allows us to rewrite commit history. Specifically I cover: amending commits, rewording commit messages, deleting commits, reordering commits, squashing commits and splitting commits.
FULL WRITEUP: https://www.themoderncoder.com/rewriting-git-history/
MORE GIT VIDEOS: https://youtube.com/playlist...
since its a fork and im not scared of force pushes since im the only consumer of my fork, if you need the history cleaned up when you do get around to looking at the changes im making, i can do that
sounds good to me
cool
now i'm going for real 🛏️
have a good sleep
i have streaming from MP3 files partially working
i can play it at half speed from a single channel
and at full speed with constant tiny dropouts
its also pitched down?
i believe the dropouts are due to the fact that NLayer reads things in an interleaved format, ive tried to hack it to not-do-that but ive been unsuccessful
i also patched NLayer to be net 6.0 and use spans in more places rather than arrays
oh apparently you already had a fork to do exactly that im dumb
DAMNIT its playing correctly now but only in the left ear
i dont really understand this code
i changed it and i can no longer get it back to this state
ive gotten close to it multiple times
was NAudio made back in the net framework days?
NAudio is kinda old
and windows only, so i generally dont consider it
i pushed my one-ear-only MP3 implementation
i am pretty sure i have a vectorized deinterleave helper exposed in soloud, have fun finding that
you have a function to interlace them
yeah im not seeing a deinterlace
in your old WIP mp3 code it used basically that exact same func
this is what i have so far, i dont understand why it would only be in the left ear
because i stepped through in a debugger and it all seems to be correct
i am going to SCREECH
SPOT THE CODE DIFFERENCE THAT MADE IT WORK
cool so now i have audio streaming for both mp3 and ogg
i am currently listening to the sound of VICTORY
aka bad apple
in glorious stereo
audio looping works too
i was worried i messed up EOF stuff
works on both OpenAL and SDL too
awesome
currently vibing HARD to bad apple in the maintainers VC
because i have achieved success
time to fix seeking as currently its just hacked together code
hol on
hmm maybe you're right
i thought i had one somewhere though
i can't seem to find it, pain
and i am 99% certain that localBuffer is not needed
i think you do to be able to deinterlace(?)
maybe theres some magic deinterlace alg that works on a single buffer or smthn but i dont know it
i'll figure it out and put it in a vectorized helper
cool, im not good with algs so im probably missing something obvious lol
i meant to do that as a utility for AudioBuffer anyways
okay i thought i had gotten seeking good but i have not, it seems to be seeking to some rando part of the song
am i stupid how do you even seek to a specific second timestamp
tried
samplerate * channels * secondToSeekTo
also tried samplerate * secondToSeekTo
both on vorbis and mp3 neither seem to be producing the correct results
oh im fucking STUPID
what the hell
i was using the WRONG FILE as reference
okay vorbis seeking works perfectly
doing sampleRate * secondToSeekTo
okay it still is going absolutely in the wrong place but i commit my current work
and now im going to BED
because im TIRED
of MP3
and its BS
and also i have coffee and code in 9.5 hours :)
7 hours of sleep EH ill be fine
lets hope my breakfast arrives early enough so i can eat it fully :^)
i got mp3 SO FUCKING CLOSE
i can seek ALMOST
i can seek to half the position i am supposed to seek to
if i multiply that position by 2
it seeks to way further than 2x in the song
so seeking ALMOST worksconcern
yeah i got seeking almost working but i have given up for now
i tried using Mp3Sharp but its bad and i gave up
i was going to begin writing a WAV decoder but then i got distracted for the next 11 hours
alright im 90% sure i narrowed the mp3 seeking down more
MpegFile has a way to directly seek to a particular TIMESTAMP instead of sample
i tell it to seek to exactly 60 seconds
and its wrong
so i think im able to open an issue here
oh wait i should probably make sure this isnt a bug with your fork, it shouldnt be but i dont know for sure
im looking at your changes and i dont see anything out of the ordinary
at least nothing that should break seeking
liar vvvv
(yes i know there is a way to get the sample position directly im just testing)
oh hmmmm
thats really weird
Cytoid creates a new MpegFile every time they seek
GitHub
Cytoid/NLayerLoader.cs at e164f56b4894b70fcdcbdfae7bacb9de1c92d604 ...
A community-driven touchscreen music game. Contribute to Cytoid/Cytoid development by creating an account on GitHub.
i wonder if there is a reason
that didnt fix the problem
it would have been very weird if it did tbh
im seeing a SUSPICIOUS
/ sizeof(float)
in a lot of things consuming NLayer
relating to length and position
not only that but a lot of unity projects using NLayer do something odd
in the 'set position' callback
they all just create a new clip
thats it
cytus is the only one that ever actually SETS the time
i am so confused at why ths doesnt work i am pouring over NAudio and NLayer issues and documentation
nothing makes sensetheres MAYBE a relavent PR https://github.com/naudio/NAudio/pull/10
GitHub
Add sample-exact seeking to Mp3FileReader by protyposis · Pull Requ...
This changeset adds frame-exact seek capabilities to the Mp3FileReader as explained in this blogpost. It also fixes frame-granular repositioning, position reporting, and handles the decoder warmup ...
did you ever have mp3 seeking fully working? or was your seeking code that you did have a WIP
seeking was indeed a joke
and my NLayer fork is WIP
i was going to implement WAV with a custom WAV decoder then i realized id have to implement seeking and i got distracted thinking of how to do sample accurate seeking
seeking? in a WAV?
how could this be any harder than a +=
would be nice to support WAV in the same manner as audacity does
(talking about the amount of data formats)
including ADPCM
JUNK
is a random identifier that appears between data identifiers
to align things
also getting sample accurate seeking with streaming is the part im not sure how to properly do
i think ill store a dictionary of the sample start index of each data
identifier -> byte positioni will align someone with a gun
WAV was just too easy to not fuck up huh
then basically go to the right data identifier, and then add the remaining samples i need to go to the sample read position
sounds fine, i do that dance in vorbis as well
cool, yeah thats a lot simpler than my brain was initially things
laying it out in text helped understand it
this would be quite easy to do
and sounds like a fun coding challenge :)
ive never written a streaming audio format decoder
only a 'read the entire wav beforehand' decoder
it's easier when the encoder doesn't lie and breaks the format spec
wav is simple enough in concept where i dont think many encoders will break spec
i will be forever salty for ogg encoders being broken for years
just for clarification, if
leaveOpen
is false that means close the stream if the reader is disposed? i just realized i dont actually know for certainya
leaveOpen==false => close on dispose
cool
oh god theres sub-specifications of WAV
forks of it to fix problems
RF64, uses a 64bit file size marker rather than a 32bit one that the original spec used
theres also the W64 format which does the same thing
but is a different format
okay ill figure that out another time, im just going to target base spec WAV for now
wow i forgot how quickly parsers balloon into large files
lmao wikipedia literally just shits on the spec and says 'the spec is confused here, heres how the spec SHOULD have been written'
IAudioStream.Seek
100% is being passed in a sample count ignorant of the number of channels for samplePosition
, right?
like when SoLoud calls IAudioStream.Seek
, samplePosition
is the number of samples (divided by the number of channels)?
okay so the WAV files by FFmpeg are just a single data
chunk
i think i will craft my own wav file in a hex editor that has JUNK identifiers and multiple data
chunks
to stress test the seekingtmk wav file
data
chunks don't have any headers after it. data
is always the last chunk and it always contains the pcm datathen whats the point of JUNK
it goes before the
data
header to provide crap bits of metadata iirc
i used to have a file with a junk chunk but i can't find it anymoreokay so apparently theres something called a "wave list chunk"
wavl
that can contain multiplehttps://sites.google.com/site/musicgapi/technical-documents/wav-file-format
according to some old site which has quite helpful listings of the chunks
but apparently its almost a hack
but with how i was planning on implementing the wav sample reading, this is trivial to support
so i dont see why not
im sure theres 1 wav file from 2003 that uses it that someone is going to complain doesnt work
for a wav file the only chunks you are interested in are
fmt
and data
you can ignore the rest, that's what i do
my reader just checks chunks until it finds fmt
and data
and then it just stops searching
(unless ofc you need other metadata)yea but thats no fun i like writing parsers
wdym by parser tho? there isn't anything to parse?
im fairly certain im parsing the wav file
any binary reading of data structures is parsing :^)
ah. i always just considered that loading but i suppose you are right
but yea creating a spec compliant wav loader is really simple. at the point though that the
format
identifier is not 1
or 3
though is the point you start panicking cause that's when the data becomes not PCM
(1 = integer pcm, 3 = floating point. i discovered this by staring at wav files with various different sample formats)i try to keep the sample count definition to "one sample = all values for channels at one time"
cool, thats what i thought
ill stick with that internally in the parser
oh apparently the WavePlayer in the silk repo doesnt follow spec
"One tricky thing about RIFF file chunks is that they must be word aligned. This means that their total size must be a multiple of 2 bytes (ie. 2, 4, 6, 8, and so on). If a chunk contains an odd number of data bytes, causing it not to be word aligned, an extra padding byte with a value of zero must follow the last data byte. This extra padding byte is not counted in the chunk size, therefor a program must always word align a chunk headers size value in order to calculate the offset of the following chunk."
simple fix tho
@techpizza is there an optimized codepath already for u8/s16 -> float already somewhere?
this is what soloud did for loadRawWave8
lol
i have not made optimized helpers for that yet
ah
wait what the fuck is
(signed)
didn't know you can just do
signed
it seems to cast the integer from unsigned to signed (surprise)i didnt know that was a thing
feels like something you'd whip up on an interview
i like writing this kind of stuff this is fun im enjoying this so far
clueless ^^^
i do enjoy data transformations quite a lot
slowly getting this read samples func down (yes i know this wont work if you cant seek but for my specific needs i dont care about non-seekable streams)
MemoryMarshal for the win
im going to combine de-interlacing and converting formats into one for loop and pray to the JIT gods that it gets vectorized
ohh i see what you mean now.
you are literally streaming directly from the file
yup
going to support some extensions to the format too, like W64, and the weird 'silent chunk' stuff
nice!
silent chunks are an interesting way to compress
not seen them before, what are they?
compression? in my WAV?!
its a chunk that only contains a single i32, which is just how many silent samples
combine tha with multiple
data
chunks
and you cut down a TON of dataohh okay
thats cool
i can't wait to write a WAV parser myself
that doesn't allocate
all the allocations are due to my unknowledge of deinterlacing and conversions :^)
im TRYING to keep it down to a single array allocation for code simplicity
i know i could do this differently by reading and converting directly from the stream
that would be allocation-less
but not right now
actually wait is that what you were going to do? thats really simple
i may just do that right now since i dont actually have any of the conversion code written yet
hows something like this then, this cuts out the allocations
i dont know how to write an effecient one here, im not good with that kind of stuff, what would be better?
is this some memory cache thing i dont understand where i am writing to alternating points in a buffer, instead of contiguously?
there are many points
and i'm tired rn
ah
i will just a write WAV helper and buffer and streamer later
fair
this is good enough for my current uses
you using loudpizza does me happy tho
oh god wait this is not good enough for my use cases its taking 1.6ms to read 1000 samples
tf taking that long
profiler time
that can't be right
uhuhhh
do you increase
read
?oh i dont do that
but i dont use it either
you return it
also, why not keep a BinaryReader field on your class
i do, i just forgot to increase it :^)
1. you need to warm up le code
2. there is Stopwatch.GetElapsedTime
Console.WriteLine(Stopwatch.GetElapsedTime(l));
👌what
no there isnt
is this a net7 thing
net7 gang
ah
loudpizza is still on net6 so thats what the test project is on :^)
i'm surprised it took them so long
okay that is MUCH more reasonable
it just had to warm up
Tier0 code is bleh
it is basically debug codegen
ouch
i forget the JIT tiers exist
i feel bad for monogame devs that got indoctrinated to turn off TieredCompilation "because of hitches"
the upgrade from tier0 to tier1 is asynchronous
oh god wait i hope that monogame curse isnt still in my engines project file ONE MIN
IT IS
NOOO
i didnt know what it meant back then
i just read
'causes hitches, disable it'
so i did
fixing immediately
we have JIT magic, might as well use it
the tier0 to tier1 is 100% worth it
tiered compilation off:
tiered compilation on:
halves draw time
makes updates like 5x faster
and inputs seem unaffected
oh wait no
those are 50% faster too, that screenshot just happened to be at an unfortanate time
i mean, it turns
static readonly
fields into JIT constants
it can eliminate huge chunks of code and stuffthank you for gaining me 1.1k fps i would have never known i had that disabled
obscure java tricks be like
pretty sure this makes tiered PGO better as well
soooo 5000 fps when
the biggest bottleneck seems to be the Draw() function, which makes sense since its quite hefty
the jit is smart when compiling tier0 code; it gathers inlining metrics and stuff at that point
so if you cut your draw method up into smaller pieces and stuff, i'm sure you can get a bit faster
won't really matter when you start drawing actual content because drivers boohoo
it is split up quite well
that highlighted code is it complaining about allocations
which is a problem i have yet to solve
oh right its complaining about a debug assert allocating
i have no idea how it is
but apparently it is
but yeah it the top level draw function calls down into here eventually
https://github.com/Furball-Engine/Furball/blob/4a9a43517dcf7daa94fb673e4a4fb301cab17cd4/Furball.Engine/Engine/Graphics/Drawables/Managers/DrawableManager.cs#L63
and this calls into every single drawable in the scene
the drawable draw method is virtual :^)
either way, ill dig into whats causing Draw() to take so long later, back to wav stuff lmao
ALRIGHT first test of playing a wav file
and its pure silence
OH i know whats happening
im not increasing the read position
oops
wait WHAt
ITS WORKING
I HEAR BAD APPLE
NO DISTORTION
nice
literally the only bug was i was just reading the first chunk of the song over and over
cool so i now just need to do this for 8bit PCM, then for floats i only need to deinterlace
is WAV 8bit PCM data signed or unsigned
i cant find much on google
unsigned
midpoint of 128?
ye
cool
i just do
sbyte.MaxValue
and i have no issues but 128 should make no difference eitherif this was zig i believe i could do some shenanigans there to support ANY bit count, since zig can have shit like a 13bit unsigned integer and it just works
okay i just listened to the entirety of bad apple 'for testing'
back to actually coding
eyyyy 8bit PCM works now too
is there such thing as 16bit float PCM data
or is that too cursed for any encoder to have implemented
not seen anything with 16-bit floats, only 32
there is also 32 bit integer format too which is just cursed
audacity doesnt have 16bit float exports
i wonder if FFmpeg does
FFmpeg doesnt either
the formats im aware of are:
8 bit unsigned
16 bit signed
(There are also signed 8 and 16 bit unsigned but we don't talk about those because I've never seen anything use them except tracker formats)
24 bit integer
32 bit integer and floats
and i think that's the "main" formats used
that's what mixr supports anyway (except 24 bit integers, they can go die in a hole)
f32 works
and so does f64 now
wouldnt 16bit unsigned sound the exact same, just phase-shifted 180 degrees?
if parsed as 16bit signed
nope, it sounds like garbage (try it, but turn down your volume lmao)
you have to subtract
short.MaxValue
to convert it to signedwould the midpoint of 16-bit unsigned not be short.MaxValue?
it is yea
yeah this is the difference between signed and unsigned lmfao
that logically doesnt make sense in my brain, let me try to write down what im thinking
lets pretend its 4 bit PCM for clarity
in the signed representation
1000 would equal 0000 (as that would be negative 0)
but unsigned 1000 is also the midpoint (but off by one?)
so any other numbers should just parse out and be the same (but with signed-ness flipped), no?
part of the problem is that pcm data is big endian so it kinda doesn't know what to do with it
OH
yeah BE vs LE will be a bigger problem
but signed vs unsigned at its worst will be 1 number off what it should be
since
1000
!= 0111
which is imperceptible to hear
(assuming this is 16bit)yea
ive not tried converting from big to little endian and then casting to signed, wonder if that would work
don't see why it wouldn't
yeah thats my thinking, if the endianness is the same
it should just sound the same
if maybe phase shifted 180 degrees
with peaks becoming troughs and vice versa
yea
id be interested to see the result of that
cause yeah typical unsigned-signed conversion on pcm audio just completely rips your eardrums apart lmao
you are probably getting trolled by endianness there lmao
ye
how the fuck do i read a 24 bit integer from a stream
i have
no idea
i've tried and failed
so i just kinda gave up for the moment
actually wait i know exactly how
what you gotta do is strip out the sign bit and convert the result to a 32 bit integer iirc
but i failed miserably
oh wait
nvm
this would work, right?
although i may get trolled by endianness
reading from a stream should be much easier than trying whatevertheheck i was doing to convert it to listenable audio, soloud should handle that for you
nah i have to give it float data
oh
from -1 to 1
so i need to convert to that format
yeah thats not gonna work
cause if you cast it to int, it will lose the signing
no it wont
im using a pointer
oh
ok
oh wait but yeah the sign will be in the wrong place
yea
thats a simple fix one sec
thats the issue i was having
nothing i did fixed it so if you can work it out lemme know lmao
this should work, right?
maybe, only one way to find out
i need 24bit pcm data first :^)
oh audacity has an export for it
just do bitshifts dammit
the runtime should be smart enough
it is absolutely not
not to mention that endianness issues will be real bad here
*you're also doing a stackalloc in a loop lol 💥
is that bad?
fuck right
stack is cleared at function end
not scope end
a h
i am pretty sure that stackalloc underline is a warning for the loop
what is the little endian order of u24
it is a warning for it
im just blind
little endian is little endian
yes well IM stupid
first byte comes first, second byte comes second, etc
oh
wait then this should work fine
no because in big endian your integer will be flipped
unless the PCM data is BE
*unless your CPU is BE
tldr
just
pcm data is big endian
byte b0, b1, b2;
uint sample = b0 | (b1 << 8) | (b2 << 16);
^^^^^^^^^^^^^
reality can be whatever i want
also
FYI for WAV file format, a RIFF header requires little endian byte order, and a RIFX header requires big endian byte order. See this.fuck RIFX amirite
this just causes everything to be XTREME BASS BOOSTED 3 MILLION VIEWS
yep, that's cause the sign is missing, so it's just processing unsigned audio
o rite
i did try to extract the sign but uh
something no worky
this still causes the same problem i feel like im missing something obvious
yea im not sure, i tried doing that and it didnt work either
my sign bit in christ
have you considered just subtracting
no i would never subtract
thats a crime in america we only need to make things bigger
more money
more nukes
more obesity rates
yea subtracting didnt work
without the bränch
yea that didnt work either i dont see why it would
alright i give up
maybe divide by 2 to the pow of 24?
i tried this but no
just static
static?
yep
im getting the music
just bass boosted
commit the division
me?
yeah if i get rid of the weird shit i did then i get the same bass boosted result
yes, div by 0xffffff
idk
i think we are all may be the stupid
this works
i told copilot "convert the signed 24 bit int to a signed 32bit int" and it did
do you need that branch?
LMAO
trying that now
i dont know
lemme remove the if
🤡
removing the if returns it to bass boosted state
oh wait i should go full AI mode here, im going to ask ChatGPT why the previous solution didnt work, and why the current one does
lets see if it can keep up with my incredible stupidity and misunderstanding of math
yea i tried all this stuff and it never worked either lmao
i am really weirded out by that OR with 0xff000000
same
i will have to try this myself tomorrow
"This code reads three bytes (b0, b1, b2) from a data stream and converts them into a 24-bit signed integer sample. The first code block correctly converts the 24-bit signed integer to a 32-bit signed integer by extending the sign bit if the 24th bit is set. This is achieved by using the binary OR operator (|) to set the high-order 8 bits to 1. If the 24th bit is not set, the high-order 8 bits remain 0, and the result is still a valid 32-bit signed integer with the same value as the original 24-bit integer.
The second code block, on the other hand, first extends the sign bit by using the binary OR operator to set the high-order 8 bits to 1. Then it subtracts 0x00800000, which would remove the sign bit, but this operation is unnecessary and could cause unintended consequences.
Finally, both code blocks divide the resulting integer by 0x00FFFFFF to obtain a floating-point value between -1 and 1, which can be used as a sample in audio processing." -chatgpt
i dont understand
like it explained the code
but it didnt really explain why one worked and why one didnt
okay i clarified my question
the sign bit is 1 bit, and setting 8 bits on a 32bit register wont keep it a 24bit int
what kind of bullshit is this
"The first code snippet works fine because it is converting a 24-bit signed integer to a 32-bit signed integer. First, the three bytes are read from the reader and then combined into a 24-bit integer using the bitwise OR operator (|). Next, if the 24th bit (0x00800000) is set, then the 32-bit signed integer is extended by ORing it with 0xFF000000. This extends the sign to the 32nd bit, making it a signed 32-bit integer. Finally, the 32-bit integer is divided by 0x00FFFFFF, which normalizes the value to the range of -1 to 1, which is the range of a 32-bit float.
The second code snippet does not work because it is trying to convert a 24-bit signed integer to a 32-bit signed integer, but it is not correctly extending the sign bit. First, the three bytes are read and combined into a 24-bit integer as in the first code snippet. Then, if the 24th bit is set (indicating a negative number), the code tries to extend the sign by ORing the integer with 0x80000000. However, this is not correct because 0x80000000 is a positive number, not a negative number. The correct value to OR with to extend the sign is 0xFF000000, as in the first code snippet. The code also tries to remove the sign from the 24th bit by subtracting 0x00800000, which is incorrect and will produce a heavily boosted result."
is it retarded?
maybe?
or did i finally lose my brain at uni today
i dont understand why 0xFF000000 works
and why thats the proper way
okay i entirely removed the working code snippet
and only gave it the broken one
i have a feeling like you're getting lucky
"The code above is attempting to convert 24-bit signed PCM data into 32-bit float audio data in the range of -1 to 1. However, the code is incorrect because it is not properly handling the sign extension for negative numbers.
In the first part of the code, the bytes are read from the RIFF WAVE file and concatenated into a 24-bit sample using the bitwise OR operator. Then, the code checks if the 24th bit is set, which indicates a negative number. If it is, the code attempts to extend the sign by OR-ing with 0x80000000 and subtracting 0x00800000.
The issue with this approach is that the subtraction operation is removing the sign from the 24th bit, which is incorrect. This results in the negative samples being boosted significantly and the positive samples being boosted slightly, leading to a heavily boosted result. To fix this issue, the sign extension should be done by simply OR-ing with 0xff000000 instead of subtracting.
Additionally, the code is dividing the final result by 0x00ffffff, which is not the correct maximum value for 24-bit PCM data. The correct maximum value is 0x007fffff, which should be used instead." -ChatGPT
anyways, does soloud take 0.0-1.0 samples or -1.0-1.0 samples 😹
-1 -> 1
i believe?
thats what has been working this whole time
it should be -1 to 1
yeah -1 -> 1 makes the most sense
uses the float better
are we stupid? it is HELL BENT on that
bitwise OR with 0xFF000000
and it worksalright it's -1 to 1
im trying a different method
ok i get it
it is turning the 32bit integer into ffffffff
makes sense
i left my brain at uni afterall
i can write that sign extension without a branch though hehe
are ternary operations not branches????
i see it's biased to C compilers emitting cmov
yeah they can be converted to math sometimes i believe
depends on the situation
or that
okay its spitting out some code thats branchless
MY EARS YOU BITCH ASS AI
i love how that sample >> 24 will always be zero
very useful
yeah no
oh hey that works
what how
idk
they are ANDing it with ff000000
so it should be 0???
unless the garbage top bits are getting divided into oblivion
AI will replace programmers for sure
for some reason none of this shit works at all for me
am i just deaf or smthn am i hearing 8 bit audio and just cant tell the difference
im not an audiophile
it seems to work
ok after closer inspection, this should work
wait why
by shifting by 8 turn it into a real 32bit int
but then you discard most of the data with the AND
i wonder if it will work if i and by
0xffffff00
insteadoh right, you can fix the discard
oh hey that works, but i dont hear a difference
i mean, the top bits of a 24bit int are probably enough to make good audio
mask with
0xf0_00_00_00
and enjoy 4bit audio lolTRUE
mmmmmm
oh yeah i can hear that
now THATs quality
3 bit audio next
0b1100_0000_0000_0000
my beloved
imagine if getting old reduced the amount of bits you can hearOH YEAH 3 BIT AUDIO IS THE SHIT
send it over sir
hint: make a soloud backend that outputs a pcm data into a file
just dump floats into a file at full blast and import in idk audacity
heres the main verse and the beginning at 3bits
i am too lazy to make a file soloud backend
ffmpeg -i recordingfromobs.mp4 output.mp3
BEAUTIFUL
1 bit audio when?
loud warning
lmao
it just sounds like unsigned audio at this point
surprisingly audible
yeah
its still a sine wine
just a very poor one
and the change from up to down is what makes the sound
so even if its just full tilt or no tilt
it still makes audible noise
deepfry with one simple bit
thats why only having the single upper byte was indistinguishable
i love how it crashes VLC
thats 255 states between on and off
lmao what
how
ask android
that is processed from FFmpeg
it stops at 10s even tho file is 23s
oh yeah it just
like
does that
time to stop being side tracked
and do 32bit ints
¯\_(ツ)_/¯
i am going to bed
good night
bam that works
yeah 32 bit stuff is easy in comparison lmao
cool so now i handle u8, s16, s24, s32, f32, f64
nice
what was your code for converting 24 bit stuff in the end?
the conversion is branchless
nice, gonna try it now
nope, still borked af
probably thanks to rust being really fucking strict on conversions 🙃
given the second audio format in WAVE is ADPCM i wonder how common it is
adpcm is still quite common i think
no idea what its used in anymore but
hmm so then i probably want to be able to read it
oh apparently seeking/looping is harder with ADPCM
since you need to decode the full block of data to get any singular sample
yeah
what you could do is work out which block you need, decode it and work out the sample from there
yeah
adpcm is cheap so it shouldn't be too bad
okay i found a page that explains MS ADPCM https://wiki.multimedia.cx/index.php/Microsoft_ADPCM
how many adpcm formats are there tf
like 3
or smthn
4
jeez
this is an incomplete list too
mpeg 👀
i hate SO much that mpeg is there
yeah lmao
use a FUCKING mp3 file
PLEASE
i will personally stab any people putting MPEG data into WAV files
lmfao
understandable
oh dear god theres more to WAV i didnt know about
"There are 3 variants of the Format chunk for sampled data" is the scariest thing ever to read
so i need to check the length of it
where are you looking for this?
my source is a site that is literally 300 years old
if the length of the fmt header is longer than the normal size, then i need to read ANOTHER size and thas the size of the extension data
the fuck is VALID BITS per sample
speaker position mask???
SUB FORMAT?
ITS A GUID
aaaaaaand this is why most wav players can only support bog standard PCM and ADPCM cause fuck this rabbit hole
i wouldnt be surprised if the cursed 2 decade old japanese wav files i have to work with are some shitty annoying format that hasnt been seen by humanity since 2005
I SHOULD PROBABLY CHECK ONE MINUTE
lmao
time to stick it in a hex editor and check
im just gonna try and load them
why pack both a wav and ogg file? I DONT KNOW
IT DOESNT EVEN USE THE WAV FILE THATS SO WASTEFUL
ah yes, numbers
okay so its ONLY a decade old
oh thank fuck its a normal file
16bit pcm data
yeah anything from like
year 2000s onwards i would be surprised if it used some weird nonstandard format
those are beat line bars and beat line beats (direct translation)
ahhh ok
what do you mean ok that means nothing
the dev used non-standard terms everywhere
i kinda just assumed bars and beats were like the things on a musical score
they're not?
nah
a h
its some random division of the BPM
i think its 1/4th or something horrible
lmao i see
anyways id best be off to sleep also, good night
good night
oh boy the decode thread just spins forever when you reach the end of the song :^)
i need to set an EOF flag and actually exit out of the
while
seeking works OOTB too
sickGitHub
Wav: Implement full Async WAV player · Beyley/LoudPizza@1b047b0
Supports PCM and Float data of the formats
F32, F64, u8, s16, s24, s32, all major PCM and Float formats
if anyone wants to judge my WAV reader
4hrs 45mins to make a full WAV reader
ill take that
https://www.aelius.com/njh/wavemetatools/doc/riffmci.pdf
oh apparently
slnt
chunks are part of the main spec
not a weird extension
okay so to handle slnt
i need to know whether i seeked to the position im playing at or whether some other sample was used previously, the best way i think i can handle this is to constantly keep track of the last sample to have been played from a data
chunk, and maintain that value for the rest of the slnt
chunk
but if you seek
reset that to 0
thats what the spec suggestsi also love when the SPECIFICation says the word 'might'
i just dug through every reference to
wavl
on github
NO ENCODERS
OR DECODERS
implement wavl
or slnt
NONEi don't think you need the 0xffffff00
you're shifting in zeros anyway
ah yeah probably
how do i fix the pops when you seek
vorbis doesnt have this problem
but both wav and mp3 have it
is there some interpolation smoothing thing you are supposed to do
lol what pops
vorbis just seeks to a specific sample, no magic
if i seek to some point in the middle of the song, theres a loud audible pop
for some reason it dont happen on vorbis
or maybe i was getting lucky idk
oh wait no its happening now, ig i was just getting lucky with my seek position with my other ogg
that is a suspiciously loud pop
yeah
im really not sure whats happening there tbh
im assuming its samples going from
0 -> some high value
THE PLOT THICKENS
it doesnt happen with OpenAL
only SDL2im doing basically exactly what you did in the VoxelPizza audio test
ugh
idk, log the samples to a file or something
i never had any loud pops on windows at least
and i seeked a lot
weird, mayhaps a linux thing then, ill log to a file and see what comes out
copilot you are the have stupid
hehe
(i did try forcing s16 mixing to be used, to see if f32 was maybe the problem (OpenAL uses s16 always right now), but that didnt help)
lemme finish writing to a file rq
copilot ingested too many builder patterns
true
alright its going to be slow as BALLS but thats all i need
whatafak
i forgot the newline
using StreamWriter writer = new("samples.txt");
i begi mean the audio plays at full speed still SOMEHOW
i crashed my text editor lmao
c# good
full text file incase you want to take a look
nothing looks out of the ordinary
OH i should compare it to what the audio looks like normally with no seeking
okay yeah looking at what it looks like NORMALLY
this is super out of the ordinary
normall the audio goes from like
2.8672945E-05
to numbers like 0.2 over a long period of time
i think that jump from 0 -> 0.2 is the cause of the popuuuh going from 0 to 0.0678 is quite a jump yes
maybe certain audio backends smooth out harsh transitions? not xlue
hmm
yeah this definitely seems like something SDL related
if i tell SDL to use alsa directly
the pop is very loud
but if i tell it to use pulseaudio
the pop is quieter
i cant tell whether this is a bug that i should report to SDL (given OpenAL doesnt have the problem) or whether i should try to fix this SoLoud side by fading for like maybe 100 samples from the last sample before seek, to the 100th sample after seek
100 samples is enough to probably not cause a pop, but short enough to not be noticable
especially if i just directly interpolate for 100 samples from the last sample pre-seek to the 100th sample after seek
just multiply the first couple samples you read after seeking with 0.1f 0.2f 0.3f etc
makes sense
er wait that wont work, what if the seek operation happens while audio is playing and it jumps from like 0.2 -> -0.2
ill try a little interpolation
see if that helps
right, so storing e.g. the last samples read into a buffer and lerping between that and currently read data sounds interesting
yup thats what im working on rn
er... it would not be last samples, it would be current sample playing
the pop is basically eliminated with 2000 interpolated samples
i think i could interpolate this smarter by basically weighting the real samples by the interpolated value
that should remove the quiet little 'static' i hear
hmm that doesnt fix the static
you can see what the 'static' is here
its minimal though
and a lot better than a pop
YES i know this code is bad and does silly allocations i am just testing
oh i think im interpolating the WRONG WAY oops
you hear static? i'm concerned
its like <10ms of 'static'
i dont think its static
but i cant describe it any other way
oh god i know why its hitting static
im stupid
i basically am creating static by accident
my interp code assumes that the getaudio is greater than the amount of samples i want to interpolate
so its basically interpolating from 0 to a bunch of random positions later in the buffer
over and over
i know how to solve this but im too tired to tbh
its 00:30
i think im heading to bed lmao
actually wait i dont know how to solve this
how do i interpolate to a value i dont know yet
do i just like
guess and check?
cus 512 samples of interp doesnt seem like enough
i think it has to be at least 2k
eh ill think more about how to structure this nightmare tomorrow
idk maybe you have an idea of how to do this
you don't
what
you can't interpolerate to a future unknown
i can if i try really hard
not really
and you don't really need to either
i can interpolate by a small value until the final 512 then i can properly interpolate the rest or smthn
yeah you just interpolerate what you have
if it's too far thats probably fine
and then the next once you get more
i just wish all the hard problems could be solved for me by unknown magic forces like how OpenAL works perfectly fine
haha
it's a rare OpenAL W
popping when seeking is just something that happens.
if you want to eliminate it, fade the audio out over the span of about 50 samples, and back in over the span of another 20 samples or so
this is how openmpt does it and it basically eliminates popping
ofc this does assume there's not a period of silence or static in the middle
yeah, multiplying a negative or positive number by a less-than-one factor should still have the desired outcome
and reduces the amount of tracking you have to do
okay ive janked together a null backend
since how often i call mix effects playback speed, im using a combination of Thread.Sleep and SpinWait to wait for exactly the right amount of time
inb4 theres some simple magic solution in soloud to solve this :^)
ooo soloud has so many backends to implement in c# time to get distracted with that
jack also expects samples in non-interlaced format
it to be specific: each channel is a separate buffer
(which makes sense given the main purpose of it is to be able to re-route your audio around :^)
man the INTRUSIVE THOUGHTS to call it the "Jack Black-end"
bruh the only jack bindings for c# is a stupid wrapper
time to run buildtools over the header and make my own
after "lunch"
the fuck is a
.dll.a
i sure do love my STATIC DYNAMIC libraries
ah buildtools chokes on it for some reason
its not handling the opaque structs
oh i forgot traverse
oops
okay Jack bindings created
time to actually continue portingSolound
for performance, i added a
mix_single_channel
function, which basically just copies directly from the internal scratch buffer to the given bufferbasically removes the whole de-interlaced -> interlaced -> de-interlaced ring-around that SoLoud itself does
well its playing at 2x speed
but its not actually fucked
holy shit i found a fucking RELIC
http://linux-audio.com/
okay this didnt work since i was mixing twice, thats why it was 2x speed
solution was to create a
mix_without_copy
then a copy_deinterlaced_channel_samples
and now it seems to 'just work'
cool so now Jack, OpenAL, Null, and SDL2 backends work
oh im really stupid
null backend is meant to not progress play head
i just accidentally created the
nosound
backend
the main problem is fading out the stream
i dont know enough about how SoLoud is structured to be able to do that
ill leave the popping fix for later
what platforms/usecases am i missing at this point
i have Jack, SDL2, and OpenAL
Jack for ultra-low-latency and more music-production based tasks, SDL2 for basically all platforms, and OpenAL for
something idk
ideally id port the raw Alsa and XAudio2 backends over too
so that i dont have to go through SDL for any unix-likes or windows
on linux Jack is available in most places that have pipewire, but for pulseaudio systems its likely not available
i also need to write some code to auto-detect the best backend to try to use
i think right now i would go the path of try Jack -> OpenAL with the buffer_callback extension -> SDL2 -> OpenAL with the thread strategy
since OpenAL with buffer_callback is much less to dynamically load than the entirety of SDL2
but OpenAL without the buffer callback extension is less reliable than SDL2
with Alsa and XAudio2, itd be
Jack -> Alsa -> XAudio2 -> OpenAL (buffer_callback) -> SDL2 -> OpenAL (raw)
jack always first, since Jack is super low latency
on linux pipewire it doesnt matter too much, but on windows, Jack is probably the lowest latency option
but its only going to be available on 1/100000 of windows systems
which is sadi'll probably add something like this since i like speeeeed
there are ways to have reasonable latency on windows
:( pipewire my beloved
it's a tiny thing im surprised SoLoud never did
tbh all of the soloud backends are really half baked
like the soloud jack backend completely breaks if the server uses a weird sample rate
(which is fixed in my version :^)
pipewire has similar latency no matter if you talk to it directly, or through jack, or through pulse
i wish this poor soul good luck
they even made the fork private
doesn't unity already have like
fmod
discord weird
https://github.com/phoboslab/qoa
im hyped for this
GitHub
GitHub - phoboslab/qoa: The “Quite OK Audio Format” for fast, lossy...
The “Quite OK Audio Format” for fast, lossy audio compression - GitHub - phoboslab/qoa: The “Quite OK Audio Format” for fast, lossy audio compression