We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

Open Cubic Player and retro music

00:00

Formal Metadata

Title
Open Cubic Player and retro music
Alternative Title
Retro music - Open Cubic Player
Title of Series
Number of Parts
490
Author
License
CC Attribution 2.0 Belgium:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
This presentation includes multiple topics mixed together * Porting a DOS multimedia program into Linux/BSD * How music was composed/stored in old type of games from the 8bit era, up into the amiga (and partly the DOS world) * How does audio/music hardware work. C64 SID, ZX-Spectrum and alike, Amiga, Adlib FM-synth OPL2/3 and General Midi As a child, I was exposed to Cubic Player. This program was a text-based music player. All the color full texts mesmerized me and it gave a direct visual feedback of how the music was generated. During teenage years I learned programming and got introduced to Linux. All the sourcecode for everything was available. The kernel, multimedia libraries, tools, all kind of APIs. If there are anything you wonder how works, you can inspect it. If you are unable resolve a specific detail in your own project, try to find another project that has done something similar! But for playback of these Amiga style modules, there was no programs that had the same charm as Cubic Player. Programs like mikmod, XMMS, Audacious only displayed playlist, maybe instrument-names and maybe an spectrum analyzer. When I discovered that Cubic Player had been released as Open Cubic Player. I grabbed the source code and started to study it. All of it was based on direct hardware access, as it was written for DOS. Direct access to video-memory/hardware, raw keyboard scan codes, hardware interrupts for timers allowing background rendering of audio if needed etc. A natural candidate for a novice programmer to port? Slowly I went through one and one single file of the original source code. * Lots of logic could be kept * Some could be thrown away like direct audio hardware drivers * Some needed heavy rewrites like video output * Assembler needed to be rewritten into C inlines * The timer interrupt porting caused a zero-day kernel bug to be discovered https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2004-0554 When text appears on the screen, and audio (highly distorted in the beginning) appeared, was a magical feeling. Progress was faster when the goal felt to be well within the reach. When you the make your code public, people start to use it... and you start to get feedback like: * Program is unable to compile on other platforms * Program crash on other platforms * Specific crashes that only happens for some few people - compiler bugs (these were more common back in the days) How did old systems playback music? Using specific hardware circuits. How is music composed / stored / playback? We will take a deep dive into these two questions on these platforms: ZX-Spectrum 128 .AY files - Using code chopped out from "aylet" Atari ST .YM files - Using ST Sound Library C64 .SID files - libsidplay OPL2/OPL3 style - libadplug Amiga style modules General MIDI - TiMidity++ Open Source makes it possible to combine the work and effort from multiple volunteers. Not everything is a always an easy walk in the park, but it sure makes it easier than writing everything from scratch when there are known working code that can be either be used as a template or wrapped around.
BitMultiplication signComputer animation
Semiconductor memoryFamilyLatent heatComputerSoftwareGame theoryBitVideo game consoleComputer animation
IntelBefehlsprozessorFloating-point unitRead-only memoryComputer fileMIDISemiconductor memoryBefehlsprozessorData storage deviceLatent heatModule (mathematics)Virtual machineArithmetic meanMP3Demo (music)ComputerEndliche ModelltheorieNetwork topologyMoment of inertiaComputer animation
Route of administrationFunction (mathematics)Moment of inertiaMIDIComputer animation
Floating-point unitBefehlsprozessorRead-only memoryWhiteboardSound BlasterComputerComputer programmingEntire functionMIDIGraph coloringWeb browserComputer file2 (number)SoftwareMultiplication signPlastikkarteSound cardCloningGame theorySimilarity (geometry)Graph (mathematics)FamilyClient (computing)Computer animation
Convex hullSoftware engineeringTangible user interfaceMIDIComputer programmingInformationLibrary (computing)Pascal's triangleTurbo-CodeSocial classProgramming languageComputerWindow functionLevel (video gaming)Source codeComputer animation
Open sourceSource codeVirtual machineMereologyCumulative distribution functionSocial classMIDIOpen setComputer programmingArithmetic meanGoogolTouchscreenGraph coloringEndliche Modelltheorie
SoftwareCubeComputer fileCase moddingSimilarity (geometry)GoogolObject (grammar)Source codeComputer animation
MIDIOpen sourceBitOnline helpDensity of statesOpen setSource code
Data typeMenu (computing)Installable File SystemImage resolutionRead-only memoryData managementBefehlsprozessorDialectContext awarenessPlot (narrative)SynchronizationHacker (term)Density of statesPhysical systemFunction (mathematics)Projective planeFile systemDensity of statesMiniDiscVotingSoftwareMultimediaComputer programmingImplementationBefehlsprozessorSemiconductor memoryProcess (computing)Operating systemSound cardVirtual memoryComputer hardwareMemory managementAsynchronous Transfer ModePhysical systemStandard deviationGame theoryMappingPlastikkartePiBitSource codeComputer animation
Electronic mailing listFunction (mathematics)Interrupt <Informatik>Computer fileProjective planeDensity of statesSimilarity (geometry)Computer virusCompilation albumLevel (video gaming)Instance (computer science)Standard deviationSource code
Data conversionElectronic visual displayFunction (mathematics)outputKeyboard shortcutTexture mappingAssembly languageDevice driverComputer hardwareFile formatDifferent (Kate Ryan album)Function (mathematics)Computer fileLoginPhysical systemComputer architectureAddress spaceGraph (mathematics)Electronic mailing listSemiconductor memoryMultiplicationSpacetimeBitDevice driverImplementationLevel (video gaming)Revision controlVideo game consoleBefehlsprozessorMatrix (mathematics)Buffer solutionAssembly languageOpen setMikroarchitekturCursor (computers)Cartesian coordinate systemoutputKeyboard shortcutDevice driverSlide ruleKey (cryptography)Computer animation
Function (mathematics)Execution unitPoint (geometry)outputComputer programmingVirtual machineCompilerSinc functionRevision controlExterior algebraBitDifferent (Kate Ryan album)Block (periodic table)Machine codeCompilation albumWrapper (data mining)Slide ruleAssembly languageNP-hardBefehlsprozessorSource code
Term (mathematics)Multiplication signPoint (geometry)Similarity (geometry)Quantum stateBoss CorporationFilm editingSystem callPhysical lawRadical (chemistry)Computer programmingMIDIBitRegulator geneCoroutineVirtual machineDirected graphSerial portHydraulic jumpException handlingSpacetimeComputer fileDensity of statesKernel (computing)Machine codeWeb browserCore dumpDenial-of-service attackExploit (computer security)Crash (computing)Software bugInterrupt <Informatik>Video game consolePointer (computer programming)Source code
AverageConditional-access moduleMaxima and minimaMultiplication signMereologyMIDIHydraulic jumpSquare numberPattern languageRandom matrixSelectivity (electronic)Computer programmingFunction (mathematics)Shape (magazine)Open sourceVolume (thermodynamics)Product (business)Pulse (signal processing)Electric generatorDifferent (Kate Ryan album)Demo (music)Variable (mathematics)Physical lawEnvelope (mathematics)LaceFrequencySource codeComputer animation
BefehlsprozessorAverageProcess (computing)EmulatorLibrary (computing)Core dumpGraphics tabletProgrammer (hardware)MIDIGame theoryLibrary (computing)ImplementationFrame problemPower (physics)Standard deviationVirtual machineProduct (business)Selectivity (electronic)Group actionSemiconductor memorySpecial unitary groupSet (mathematics)Different (Kate Ryan album)Core dumpComputer fileAtari ST
Content (media)Game theoryMachine codeMIDICore dumpIterationCommodore VIC-20TriangleSawtooth waveSource code
Musical ensembleMountain passCloningWitt algebraCommodore VIC-20Sawtooth waveMIDIIterationMessage passingMathematicsSemiconductor memoryFilter <Stochastik>CoroutineVolume (thermodynamics)TriangleStandard deviationDemo (music)Game controllerGame theorySystem callGraph (mathematics)Form (programming)Computer animation
Commodore VIC-20BefehlsprozessorAddress spaceVideoconferencingMoment of inertiaOpen sourceGame theoryProjective planeMIDIImplementationPlanningComputer animation
Operator (mathematics)Machine codeMIDIDrum memoryTotal S.A.Function (mathematics)Loop (music)Operator (mathematics)Multiplication signHarmonic analysisPolar coordinate systemComputer animation
Sign (mathematics)Term (mathematics)Different (Kate Ryan album)MIDIFrequencySinc functionOperator (mathematics)Harmonic analysisDemo (music)Commodore VIC-20Computer animationProgram flowchart
Maß <Mathematik>FingerprintSound effectPunched cardSound effectMIDICommodore VIC-20DigitizingPolar coordinate systemVolume (thermodynamics)Multiplication signBitModule (mathematics)Parameter (computer programming)Electric generatorSampling (music)Text editorCommitment schemeBuildingHypermediaWind tunnelRight angleSpecial unitary groupSampling (statistics)
MIDIStructural loadGame theoryDatabaseElectronic mailing listComputer fileInstance (computer science)Projective planeMultiplication signMusical ensembleHypermediaTouchscreenDrum memoryEvent horizonMIDIElectric generatorGroup actionStructural loadDifferent (Kate Ryan album)Graph (mathematics)Computer fontStreaming mediaDivisorSelf-organization
Linear mapFile formatComputer fileSoftware bugLibrary (computing)MP3VotingFile format
Open setCubic graphLibrary (computing)Magneto-optical driveMultiplication signSlide ruleOpen sourceLibrary (computing)AuthorizationMIDISoftware bugProjective planeCubic graphComputerFeedbackComputer animation
FacebookPoint cloudOpen source
Transcript: English(auto-generated)
Hello, my name is Stian and I'm the person that rewrote and ported OpenCUBE Player over to Linux and BSD. And then many probably has a question why, and to do that I want to step back in time
a bit to my childhood. So the very first computer me and my brother had was an old Apple IIe and received that with a couple of games and a basic tutorial. So that got me curious into software programming a bit. And of course we also had an old game console that we could connect to our TV.
But as we grew older my big brother bought a computer. And this had awesome specifications of a 33 megahertz CPU that we of course upgraded to 66 megahertz.
It had a whopping 4 megabytes of memory that of course we could upgrade to 20, still not so much. And 200 megabytes of storage. And most of you can probably guess that if you have an MP3 collection of music you
cannot fit so much music on this computer. Which means that back in the days you had other means of music which we back then called module files or Amiga modules. But this computer only had a PC speaker or what's known as a beeper.
And I will do a little quick demo about how music would sound on such a machine. So we had inertia player which could actually output audio into the speaker. And the music quality would then come out of the speaker so it would be even worse than this.
But at least it was music. So yes, let's get that out of the way, where again? I need to get the mouse out. Okay. Easier.
So yes. So my brother, he decided that we wanted to have some better audio quality. So he bought an audio card which was a clone of a samblaster card. And with that we could suddenly have better music and we could also have music in our games as well.
And at this time we also got access to Cubicleer which I found to be an awesome software. So let me get DOSBox up and running again. Two seconds.
So you would be presented with a file browser similar to like this. And your music would be presented with nice colors. And the audio was much better as well.
And for me, my entire childhood of music was in software like this. So yes. I really miss those days from my childhood. I have a nostalgia for it. So, for our computer I started learning programming with Turbo Pascal.
And the available information for that was not that great. My local library had some few books of it. All the books seemed to really go into learning to make like an inventory of your music collection. And that was kind of the level you would learn about when you read those books.
So later in high school I learnt a new programming language, Delphi, which basically was Pascal wrapped into Windows instead. So I didn't quite get so much more use out of that. But some friends in the class above me introduced me to Linux.
And he gave me a copy of a Linux distribution on CDs. And with those were also source of everything. And suddenly you could go into every part of the machine. Anything you wondered how it worked, you could find the source code. If you wanted to make your own things, you could copy paste from other things.
So for me, open source was a real opener for learning how to program. But music back in 2000 on Linux was not that much fun though. We had a mic mod to play modules.
Back then it didn't have colors yet, but it didn't manage to find screenshots on Google. That was that old actually. And if you run a graphical environment, you could have XMS and similar players. But it didn't give me quite a feeling if you want to play old Amiga files. It didn't show you anything about how it actually worked.
And I really missed it. It had that old nostalgic feeling. I could never really be solved. So I kept on watching on CUBE player. And one day they had renamed it to OpenCUBE player and released the source. Yes!
And if anything is open source, that means that everybody can use it. Like that's how it works, right? No, it just means that you can compile it on DOS. It didn't really help that much on Linux. So I felt a bit disappointed as well. But hey, what can you do when you are young?
You download it and you take a look inside. And for me, what I did is that I started just with a blank project. And I started first to copy over the main function. But let's first take a little look at DOS.
DOS is what many of you have never used. It's a disk operating system. And as the name implies, it has a file system API. Yes! But if you have graphics, that means that your software would talk directly to the graphics.
So that doesn't port well into Linux. Memory management. Well, you have one megabyte memory. But the program had access to the CPU. And they could change the memory maps.
Also with the programs being only 16-bit. But the programs could do whatever they want. They could change the CPU over to 32-bit mode. And DOS did not have anything or no knowledge of processes. It was just a single process. It was your software.
And lastly, there's no sound API in DOS. Which means that all software written in DOS talk directly to the sound cards. So if you had a multimedia software back in DOS, it means that you had to implement hardware support for everything. And that your multimedia program or game would be an operating system in itself.
When you compare it to modern standards. So, yes. I started to allocate my main function, mains. And I copied that into a blank project. And I see if it could compile.
And first thing I notice is lots of things can be removed. So for instance, to check if you had a virus infection in DOS, doesn't really matter. So that we could easily remove. So next dependency it got was to a list of initializers.
And the first initializer was to configure all the interrupts. In Linux, we don't really need this. So lots of things we can simply remove. Next thing came on the list was actually support for DLL files in DOS.
Which is kind of special since most people don't think DOS has DLLs. And they actually do not do that. But some C compilers have their own support for this.
But hey, in Linux we have something similar. In libc we can open SO files using some built-in functions in libc. So lots of this functionality we could simply strip out and easily replace as well. So API conversions, that had to be done.
So DLLs we already mentioned. Those we could remap to libc's own implementation. Next thing on the list is graphical outputs. And in Linux it's more common if you have a text pod application to use end cursors.
Or if you run it in a console you can actually get direct access to the buffers using some special devices. Keyboard input is also quite simple actually in Linux. We either use end cursors or you can read standard inputs. And you can map up all of the special keys.
And like up and down. Next thing on the list was the audio mixer routines. They were written in assembler. So those we will see in the next slide a bit. I had to rewrite them so they could compile with GCC.
Audio hardware drivers. In Linux we have the advantage that Linux can handle audio for us. And this we do either using Open Sound Systems or ALSA. Later I also added support for X11 and SDL.
So suddenly we have a big matrix of different inputs and output devices. And this also makes it possible to run it on quite large collections of different Unix based OSs. But of course things don't always work out. The first problem arrived when a person tried to run this on an old Mac.
A really old one. An M68K CPU. And that has a different endian. And some of you probably never heard about an endian before. So I'll do a quick introduction to that.
So first if we have our memory as a long list of addresses. Each address can store one byte. So what do you do when you want to store two bytes into this system? You can choose to have one byte before the other.
And both are correct. This is called little endian and big endian. Different CPU architectures and file formats choose to implement different ones. And why they choose? I don't know. But it means that whenever you load a file you need to be aware of which endian it is stored in.
And convert it to whatever your local CPU actually expects. So with that out of the way, I mentioned that original mixers were written in assembler. And this was probably chosen because C compilers and C++ compilers back in the days were not very efficient with the code they produced.
And the machines were not super fast. So with code that was really very important would be handwritten in assembler. All of these functions from your program.
I initially chose to keep the assembler mostly as is. Hard to see on the slide. But I was put this inside a little wrapper and you can glue it into C as is. But you need to inform GCC about which registers are used as inputs and outputs.
And suddenly GCC can use the assembler block as is. But this is not very compatible when you want to have different CPUs and also when you want to have 64-bit support. So all of the assembler functions need to have alternative versions in C. And I even had one contributor writing the assembler functions to C for the floating point unit.
So I didn't have to do everything myself. So, let's jump. Yeah, one more thing. Background idler. Back in the year 2000s, machines were still a bit slow.
And if you open the final file browser inside kube-player, the music would every now and then skip a bit. So I choose to look at how this was sold in DOS. And in DOS they would use a timer interrupt. And in Linux you don't have interrupts in a program.
But for timer we have something similar. We have something called sigtimer and you can instruct the kernel to give a signal on that signal handler at a given interval. So I chose to copy-paste the original code from kube-player for this.
But it kept on locking up my console. And early in the night I initially did not know why this happened. So I was able to get out a little piece of code. And initially I thought it would be a bug in my code or GCC and that my code just simply locked up my terminal.
But the machine was still okay. It turned out to not be that. It turned out that I had hit a zero-day exploit. By pure accident. So it turns out that the FPU is actually async with the rest of the CPU core.
So when you do a store and restore of all the registers in the FPU, it doesn't happen immediately. It takes a little time before it actually happens. And what I did in the original code that I kept from DOS is I wanted to preserve the state of the FPU.
Because I didn't know if this was necessary to do or not in a sigtimer. And I had, by mistake, left out a little star. So the pointer was not dereferenced enough amount of time. So this code actually crashed, but the crash didn't happen immediately. It happened after the code returned back into the kernel space.
And the kernel space exception handler routine didn't expect this kind of things to happen. So it kept on trying to restore the FPU over and over and over again. So you basically had a DDoS attack as long as you had a login access.
So let's jump back in time to see how music used to be done before. And this chip looks like a weird name. It had many different names, it was sold under many different brands. And if you look deep inside it, we can see that it has a little pattern.
We have three different pulse generators, they named it. Today we'll probably just call it square wave generators. And a simple noise generator. For each channel you could choose to use the pulse generator or noise or both.
They added what they named a global envelope generator. Very advanced name. Basically it's a shape you can choose and you can choose how fast this shape goes. And this can be used as your source for the volume adjustment.
And each of the three channels could then choose one of these. One too far. To either choose the global envelope generator or a statically set volume. So how does this actually sound?
Start a little demo program. So this is what the... louder. So we don't have so many knobs we can twist and turn.
But hey, we can make sound. Let's get that closed away before we kill any more ears here.
So this chip had three square wave audio outputs and was used in a big selection of products. Including the ZX Spectrum 128, CPC, Atari ST. And common for all of these machines are that they have very small amount of memory.
And there were no standardized way for how the music should be stored and played back. And also a very limited amount of processing power per frame. Which is why many games also only had music at the intro and not during the game as well. And at two different occasions I got asked if I could implement support for different kind of music from games.
The first one was to use iLet which is a library that emulates the CPU and the sound chip from the ZX Spectrums and some similar machines.
And the other request was EM files which is using SD sound library. This one instead of emulating the CPU it just has stored one long dump of what the registers were. So how did this music sound?
So we can have music. Yes, music is nice.
But how did they actually make this music? If we look into a dump of the music from one of those games it's actually machine code. It was handwritten and either the music composer needed to learn how to make machine codes or the music composer needed to cooperate with a programmer.
And they needed to cooperate for how to store the music and how it should be played back. So next up, the next iteration of sound chips happened with the Commodore 64. Here they chose to have instead of only square waves they added support for sawtooth and triangles as well.
And instead of having one global volume generator each channel has its own ADSR which is Attack, Decay, Sustain and Release.
Which basically means that you can choose how one specific voice, how fast it will turn on and how fast it will turn off again when you play a note. And many people also say that one big change for this was that they added filters. That you could actually low pass and high pass the audio.
So let's do a quick demo for this chip as well. So suddenly we have way more knobs we can turn there.
So how did music sound then with the chip? And it was luckily that the music was played just recently was available on the Commodore 64 as well. So this is why Commodore 64 is said to be a very important change for how music sounds.
Because it's still only three voices but since we have much more control of what those three voices do the music sounds better. So Commodore 64 also had more memory per standard which means that the audio routines for rendering the music could also be bigger.
Which means that more games would actually feature music as the game was playing and not just during before the game in the introduction. You give two chips to clock it?
Timer chips are really good. Yes. So next thing up. Yes. Also the implementation of playing back this music is using SidPlay which is another open source project.
And as well Sid files the music is still done using machine code so not much has changed there though. So what's changed then? In the PCs we were starting to see something named OPL chips.
And these chips would feature up to nine channels. Each channel would have two operators that were working in the same frequency but they could be offset to have different harmonics. These could either play audio at the same time or they could be looped back together. So that one output of the first operator would be added to the frequency into the second operator.
And they had a total of nine channels. Three of these channels could be replaced with drums. So how does this chip then sound like?
Suddenly we got even more knobs we can twist and turn. Let's do different harmonics for the two operators.
One thing that changed a lot since Commodore 64 is that all of the sounds are based on sine waves. So let's do a super quick demo of how what music sounds like with this chip.
So this would be the typical music of the start of the DOS era.
So what other chips did we have around in the world? Sid jump a bit in a short time. So Commodore didn't give up even though the PCs were coming to the market. They came up with Amiga.
And on Amiga we had a sound chip and they removed the idea of having these synth generators. Instead you would play back audio samples. And you could choose how fast these audio samples are played back which gives you different notes and you can adjust the volume. The Amiga features two channels for the left speakers and two for the right.
So a typical music editor on the Amiga would look like this. Where you have four major columns controlling each of the four channels on the sound chip. Each of these columns you can subdivide into a note which gives you the initial pitch of a note.
We give it an instrument so typical Amiga modules initially only had typical support for 16 instruments. Hence only one digit. You could have a volume, effects and parameters to that effect.
So what kind of effects could we expect to do with this sound chip? It's so basic in design right? You can actually do quite a lot by adjusting the pitch alone. Adjusting the pitch alone you can probably do most of the things you can do on an electric guitar. Dragging your hand up and down or vibrating and all kind of effects.
The same also with the volume. By the volume you can slide up and down or you can do tremolo by vibrating it quickly on and off. Next generation of audio in games. First comes the question, what was music?
Well, you can divide music into instruments and note sheets. And here a new standard come up with keyboards, General MIDI. They went through all of the instruments and made it into a long database. With major groups like pianos, drums, organs and music sheets.
A MIDI file has 16 channels. Each channel you can look up as an actor. Which means that you can only play one kind of instrument at any given time. But you can tell it to change what kind of instrument it has.
So MIDI is basically a 16 person band. And the note sheet you can convert into a list of events. When to turn on and off different notes and what instruments to play. And in order to support MIDI files, we use TMDT. It's a very old project that loads sound fonts and renders the events given in the MIDI file to an audio stream.
So, other file formats. MP3 files were used by using AMP, which is an old, old engine to decode MP3 files.
It is buggy and instead of bug fixing it, it was easy to just use libmod, which basically all this distros has installed anyhow. Same with OGG files, FLAC files. All of those are standard available in a distro, so just use the libraries.
And VAV files was already built in. It's very basic, easy to parse them. So, do I get requests for new formats? Yes. But luckily, many of them are already open source and you can copy paste in and out from them.
So, last slide. Thank you all. And making a project open source is not a negative thing. It makes it possible for you to get feedback, bug fixes, and if you ban the project, others can pick it up and convert it. So, thanks to the original authors of Cubic Players, contributors, and all different libraries that
are open source that I can either use as is or copy paste out of. And some example sources of music. Thank you.
I think my time is up, so I don't think we have so much time for questions. So, if you have any questions, you can either send them to Fostum or you can grab me out in the hall.