Mp3 decoding

Discussion of development of software for any "obsolete" computer or video game system. See the WSdev wiki and ObscureDev wiki for more information on certain platforms.
User avatar
Memblers
Posts: 4055
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: Mp3 decoding

Post by Memblers »

I tested 1.1, the audio stops after 10 to 16 seconds (it's not consistent), ctrl+c allows it to close. One time I didn't press ctrl+c after audio stopped, I tried opening the mp3 in another player (MPC-HC) with mp3play still open, and that gives me "file not found" error.

Here are the results with /test. My CPU is Core i7-6700K @ 4 GHz

Code: Select all

nocash mp3 decoder v1.1, 2024 martin korth, press ctrl+c to quit, BDS now
file: pisse.mp3
file size: 2,584,725, id3 size: 110,602, tag size: 0
input: 44100 hz, 2 channels, 234 kbit/s
output: 44100 hz, 2 channels, 16 bit
audio duration 84,584 milliseconds, decoded in 219 milliseconds
 clock cycles per second:
 read header     2,865
 read extra      1,292
 read granule    15,312
 append main     9,124
 read scalefac   44,005
 xlat scalefac   39,157
 read huffman    1,513,922
 ms stereo       89,766
 i stereo        0
 reorder         6,681
 antialias       269,460
 imdct           767,783
  imdct36        687,836
  imdct12        9,270
  imdct0         40,841
 synth/dct       3,596,468
  synth.dct32    862,826
  synth.output   2,557,517
 total           6,427,743
 
My older PCs aren't around anymore. I had a 486DX2/66 when I first found some MP3 files, I used Cubic Player for DOS and it wasn't fast enough for for it (but I have no memory of what bitrate the files used).
User avatar
Dwedit
Posts: 5000
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Mp3 decoding

Post by Dwedit »

nocash wrote: Tue Sep 03, 2024 6:36 am Yes, a DOS version would be neat for older PCs, it's just not very easy to run 32bit code in DOS, and it's probably not worth the effort, unless there is a remote chance that it could be actually fast enough to work on (fast) 80386 processors.
Does HXDOS support the waveout API?

Tested it in HXDOS on dosbox. It kind of runs, but it has no sync at all. It just outputs buffer chunks, skips ahead, more buffer chunks, etc. Like a cd player seeking forward. Most likely a problem in HXDOS, but I've seen dosbox have problems with timer emulation before.
Last edited by Dwedit on Tue Sep 03, 2024 12:06 pm, edited 1 time in total.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
TmEE
Posts: 999
Joined: Wed Feb 13, 2008 9:10 am
Location: Norway (50 and 60Hz compatible :P)
Contact:

Re: Mp3 decoding

Post by TmEE »

nocash wrote: Tue Sep 03, 2024 6:36 am
TmEE wrote: Mon Sep 02, 2024 4:46 am Desktop with C2D E8600 @ 3.33GHz :

Code: Select all

audio duration 84,584 milliseconds, decoded in 245 milliseconds
Did that come out with the clock cycles counters being all zeroes? If yes, then there seems to be a small problem in my code for detecting RDTSC opcode support via cpuid register.

Yes, a DOS version would be neat for older PCs, it's just not very easy to run 32bit code in DOS, and it's probably not worth the effort, unless there is a remote chance that it could be actually fast enough to work on (fast) 80386 processors.
No, the numbers were not zero, I'm not sure even why I omitted them... Here's the output from few more runs on the C2D machine :

Code: Select all

nocash mp3 decoder v1.1, 2024 martin korth, press ctrl+c to quit, BDS now
file: pisse.mp3
file size: 2,584,725, id3 size: 110,602, tag size: 0
input: 44100 hz, 2 channels, 234 kbit/s
output: 44100 hz, 2 channels, 16 bit
audio duration 84,584 milliseconds, decoded in 207 milliseconds
 clock cycles per second:
 read header     3,928
 read extra      2,980
 read granule    18,663
 append main     48,217
 read scalefac   50,035
 xlat scalefac   50,614
 read huffman    1,477,371
 ms stereo       138,346
 i stereo        0
 reorder         9,026
 antialias       314,674
 imdct           1,010,725
  imdct36        885,331
  imdct12        12,404
  imdct0         59,068
 synth/dct       4,806,772
  synth.dct32    1,302,770
  synth.output   3,290,673
 total           7,988,837

audio duration 84,584 milliseconds, decoded in 210 milliseconds
 clock cycles per second:
 read header     3,905
 read extra      2,992
 read granule    18,527
 append main     47,841
 read scalefac   50,911
 xlat scalefac   50,431
 read huffman    1,468,208
 ms stereo       137,987
 i stereo        0
 reorder         9,437
 antialias       313,572
 imdct           1,006,136
  imdct36        887,092
  imdct12        12,400
  imdct0         57,673
 synth/dct       4,844,779
  synth.dct32    1,330,984
  synth.output   3,301,224
 total           8,008,334

audio duration 84,584 milliseconds, decoded in 265 milliseconds
 clock cycles per second:
 read header     4,010
 read extra      3,035
 read granule    18,659
 append main     48,508
 read scalefac   49,681
 xlat scalefac   50,455
 read huffman    1,468,441
 ms stereo       135,293
 i stereo        0
 reorder         9,019
 antialias       318,171
 imdct           1,009,841
  imdct36        889,603
  imdct12        13,251
  imdct0         58,153
 synth/dct       4,844,708
  synth.dct32    1,306,638
  synth.output   3,324,020
 total           8,014,242
There can be significant variability in the decode time, I even saw times as low as 310ms.

You could do unreal mode, and not even have to return to DOS, at least for benchmarking purposes although I am not totally sure about getting file read to memory first for further processing... trying out unreal mode is in my todo list.
Joe
Posts: 663
Joined: Mon Apr 01, 2013 11:17 pm

Re: Mp3 decoding

Post by Joe »

nocash wrote: Tue Sep 03, 2024 6:36 am I would have considered that as safe technique, unless the RMW-steps can somehow overlap on multi-core processors?
On x86, RMW instructions are not atomic (except XCHG). You need a LOCK prefix to prevent another core from modifying the variable between the read and the write.

The LOCK prefix (and XCHG) can be very slow, especially if the variable is not naturally aligned.
tepples
Posts: 22785
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Mp3 decoding

Post by tepples »

nocash wrote: Tue Sep 03, 2024 5:29 amAnd alltogether the [original PlayStation] console, TV screen, cdroms, and controller would make a pretty decently clumsy mp3 player (although back in 1995, that might have been cutting-edge technology).
Playing CDs (or, soon, MP3 CDs) on a PlayStation would be no clumsier than playing them on a DVD player. Consider that when the PlayStation 2 console launched in Japan, the most popular disc purchased along with it was The Matrix on DVD-Video. (Source: "PlayStation 2’s chaotic Japanese launch was 20 years ago today" by Andy Robinson)
GBA has 16MHz ARM7, also RISC-like opcode timings, more addressing modes, conditional opcodes, fast 4-cycle multiplier, about 14 cpu registers, 32Kbyte fast ram (and also quite fast vram), I guess the overall performance could be similar to PSX. But the 32Mbyte rom size limit might be a bit of a problem for mp3
MP3 at 32 kbps would sound better than GSM at a similar bitrate, and GSM was already good enough for 2 1/2 hours of jogging music and for background music in Luminesweeper.
I don't know if there are any multi-game flashcards with SD card slots (and the SD card could be accessed from ARM code).
People used to break their music collection into 80-minute playlists to burn to CD. A playlist for GSM Player on GBA can be nearly twice as long as that.

Older SD adapters (GBA Movie Player, SuperCard, M3) are compatible with DLDI drivers. There also appears to be a disc I/O library for EZ-Flash Omega by felixjones.
profi200
Posts: 68
Joined: Fri May 10, 2019 4:48 am

Re: Mp3 decoding

Post by profi200 »

This one might be better since the Everdrive GBA is also supported.
https://github.com/afska/gba-flashcartio
Oziphantom
Posts: 1670
Joined: Tue Feb 07, 2017 2:03 am

Re: Mp3 decoding

Post by Oziphantom »

The PS1 is not that clumsy of a CD player, it gave you a whole TV for the interface and a directional pad. Vs the small buttons and display on a CD player it was very practical to play CDs on it. The downside was that it needed/consumed the TV at the same time, but gave you a controller on a long cable to change things.
User avatar
TmEE
Posts: 999
Joined: Wed Feb 13, 2008 9:10 am
Location: Norway (50 and 60Hz compatible :P)
Contact:

Re: Mp3 decoding

Post by TmEE »

You could also use it blindly because every playback related function also had a button assigned to it, i.e start=play, shoulder buttons changed tracks or seeked but TV is certainly convenient. We definitely used the machine as a CD player in past, my family actually never had a dedicated CD player lol. First via PlayStation, then via DVD player.
nocash
Posts: 1410
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: Mp3 decoding

Post by nocash »

I meant a bit clumsy in comparision to fingernail-sized mp3 players with 120GB storage and built-in battery. For the PSX, yeah, we had portable color TV, but you'd probably need a trolley and power generator if you really wanted to carry it around. The extra range with long controller cables is an argument though. And the TV speaker has more boom than smaller mp3 players. Maybe it's better than I thought (if I get it working).
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
nocash
Posts: 1410
Joined: Fri Feb 24, 2012 12:09 pm
Contact:

Re: Mp3 decoding

Post by nocash »

Joe wrote: Tue Sep 03, 2024 12:27 pm On x86, RMW instructions are not atomic (except XCHG). You need a LOCK prefix to prevent another core from modifying the variable between the read and the write.
Many thanks! I didn't knew about that LOCK prefix at all.

I have uploaded a new version, v1.2, that should hopefully fix the hangs-in-playback issue. In case it doesn't work, the zip contains three executables:
Mp3play.exe compares two incrementing counters (instead of using a single increasing/decreasing counter).
Mp3lock.exe uses the lock prefix (it occurs less than 80 times per second, so it shouldn't cause slowdowns).
Mp3wom.exe sends everything from inside of the callback handler (that's somewhat most elegant, except that microsoft states that one shouldn't do that, and it requires a weird call/retry trick because waveout initially doesn't realize that its new waveout handle is actually a valid handle).
Dwedit wrote: Tue Sep 03, 2024 11:49 am Tested it in HXDOS on dosbox. It kind of runs, but it has no sync at all. It just outputs buffer chunks, skips ahead, more buffer chunks, etc.
Good idea. Maybe that could help testing benchmarks on old PCs (if HXDOS is easier to install than windows).
I've also posted in vogons.org forum, I guess they have old PCs for doing such tests.
Don't know what is causing the frame skipping, maybe the waveout callback doesn't work, or it's also a problem with the increasing/decreasing counter.
TmEE wrote: Tue Sep 03, 2024 11:59 am There can be significant variability in the decode time, I even saw times as low as 310ms.
Yes, the milliseconds are just the whole time from start to end, including what other tasks are doing on the same cpu core. The decode frame function (and clock cycles measurements) are done in a critical section, so they should be more accurate, without getting messed up by other tasks.
homepage - patreon - you can think of a bit as a bottle that is either half full or half empty
User avatar
Dwedit
Posts: 5000
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Mp3 decoding

Post by Dwedit »

Still gets stuck. Tested all EXEs. MP3WOM doesn't seem to play anything at all.

Thread 1 (the thread that calls waveOutWrite) ends up inside "WaitForSingleObjectEx" and never leaves.
Thread 5 (the thread that calls waveOutUnprepareHeader) ends up inside "RtlEnterCriticalSection" and never leaves.

That's deadlock. Each thread is stuck waiting for a lock that the other thread has to release.

This has nothing to do with forgetting a LOCK prefix on a RMW instruction.

----

Found it on MSDN, MSDN says (regarding waveOutProc)

"Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock."

So yeah, the audio callback is clearly doing something it's not supposed to do. Callback is supposed to return very quickly and not call any wave functions, and just notify code elsewhere that it's time to process more audio. MSDN suggests using PostMessage (for a window) or SetEvent (for a handle). SetEvent is nice because it sets a kernel object to an alerting state, and gets you out of a WaitforSingleObjectEx call.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
TmEE
Posts: 999
Joined: Wed Feb 13, 2008 9:10 am
Location: Norway (50 and 60Hz compatible :P)
Contact:

Re: Mp3 decoding

Post by TmEE »

nocash wrote: Sun Sep 08, 2024 4:08 amMp3wom.exe sends everything from inside of the callback handler (that's somewhat most elegant, except that microsoft states that one shouldn't do that, and it requires a weird call/retry trick because waveout initially doesn't realize that its new waveout handle is actually a valid handle).
That is how all my Windows software that makes sound works underneath. I found it to be the only way to get a rock solid sound stream with minimal headache, it appears to work properly in all Windows flavors too, despite the "don't do this" warning.
Post Reply