Bintracker Bintracker: in search of the ideal tracker utz In the beginning there was a beeper You probably already know that I have been I work on music engines and wrote there are quite a lot of them, mostly for one-bits─ beeperZX Spectrum,and also forAtari 2600, Dragon/CoCo, etc. It is clear that one thing─ the music engine is not enough - well─ wife is also an instrument for writing music under it. Initially I solved this problem using the conversion of music text from the fores─ mat XM and wrote such converters. But what the more powerful my engines became, the more they would─ is it more difficult, and converting from XM has become uncomfortable. I wrote engine after engine, and not─ the engines used were simply accumulated for mo─ on the hard drive. Fortunately,Shirubegan add some of them to1tracker,but we soon encountered restrictions 1tracker.But I still wanted to use these engines, so at the end2016was born plan. The plan was that I myself would... I'm writing my tracker. I should have anyway learn to program for real (I, so to speak, got into assembly language with─ completely by accident a few years ago, and I didn’t study programming at all before this─ nuyu), and here I would still have the opportunity realize your vision of the “ideal” tre─ kera. But in my enthusiasm and naivety I I didn't take two things into account. Firstly, my vision the ideal tracker turned out to be quite foggy─ nym, to say the least. Secondly, I clearly underestimated the amount of work. However, this and not bad, otherwise I wouldn’t even have started! My idea of the "ideal" tracker looked like something like this: 1. The tracker should support without any problems─ create all types of music engines, through unified user interface. 2.The user interface should be simple and effective. 3. The editor must be powerful. 4.The editor itself should not be an ogre─ restrict the user, you can even allow "shoot yourself in the foot." Needless to say, I was fascinated the above-mentioned 1tracker, which forward─ recently implemented support for multiple engines through the plugin mechanism. I wanted to continue this concept, but cure some tests─ lems of1tracker itself. - Plugin for 1tracker - essentially bare implementation of the conversion code from the standard format .1tm into a binary. This approach, co─ of course, flexible, but with such a system new plugins are difficult and tedious to write. This will be done─ takes a while to master on the part of engine authors. -As I said, some of my engines require features that are not included in 1tracker. The tool editor is especially limited─ tov and lack of tables. -Many exotic platforms, with which─ which I deal with cannot be supported in 1tracker, because it works through Game_Music_Emu. - I certainly love minimalism, and in rejection of patterns in1trackersomething there is, but it cannot be denied that such a thing is necessary─ a simple approach can scare off a lot of people. this, as well as the lack of mouse support. To solve the first problem, I came up with MDAL (Music Data Abstraction Language - music data abstraction language).MDAL defines two standards calledMMOD and MDEF . MMOD - standardized music module format. This is, in essence, text representation of the tracker module, like .vt2 in Vortex Tracker or .1tm in 1tracker, but with some ideas from musical notations likeMML.What about─ is MDEF, then this is the format for describing the config─ walkie-talkies for a specific music engine. It indicates which elementsMMOD are used─ are in place and how the output data will be constructed─ new Pay attention to a couple of important ones from─ lichen First, the files MDEF describe configuration,and not code, like.1teplugins for 1tracker. Secondly, filesMDEFeven do not describe the algorithm conversion to binary─ nickname The algorithm must be completely contained in the universal compilerMDAL. So, the next step was to write─ Get this magical compiler. And so do I did, and I really succeeded in knowing to a considerable extent to carry out the plan. Then I wrote a graphical interface for it─ face, which became the prototypeBintracker (now, of course, it is outdated). This proto─ the type wasC++,contained a custom emulator─ torusZX Spectrumand custom view set─ user interface elements, reali─ called withAllegro.Some even wrote some great 1-bit tracks in it! However, it soon became obvious that its design had serious flaws. It was simply unrealistic to write custom─ new emulators for all platforms that I wanted to support. User Inter─ face took too much time at a time─ work and at the same time was buggy. But the most important part─ However, it became clear that the compilerMDAL I couldn't seesupport even half of mine own engines, not to mention others. And in general, by that time I was already dissatisfied that basic implementation of the tracker, my view─ the concept of the “ideal tracker” has changed greatly─ elk, and the current implementation is not even close would come close to this. Second attempt I put the project aside for a while, and then... preparing for the inevitable: rewriting everything─ go from scratch. I've already been sucked into the rabbit hole hole of (modern) programming, and I started looking at other languages besides C/C++. And so, in the winter 2017/2018 I sat in some wilderness without access to the Internet and tinkered with Nyquist,mysterious descendant Lispwhich is used as a script language in the audio editorAudacity. Having almost no documentation, I couldn’t─ nothing to understand, but was fascinated by the syntax, which was very different from everything I seen before. I should have stopped at this. But I focused instead on the idea that the compilerMDAL mechanism needed scenarios to compensate for what is not can be solved with a configuration file. Excess─ don't say that script writing is the language─ I was supposed to becomeLisp.In the end I settled on the dialectof Lisp,which is lu─ best suits me as a minimalist: Scheme. When I was fiddling with rewriting com─ epilator MDAL about six months, I understood two things: 1. interpreterScheme,which I planned to implement, did not fit well with object model C++, and, more importantly, 2.writing a compiler and tracker inC++ It will simply take too long. So that I took a deep breath, threw away these six months of coding and started again, rewriting the entire project is onScheme.Back to the beginning─ lu, in a little over a month and by 1/10 volume─ ema code I was sure that I was on the right ways. Howmentioned earlier, my vision the "ideal" tracker has evolved, and according to as I progressed it should have develop further. It's still changing por. The prototypeBintrackerproved that the general the idea of supporting various sound engines in a single interface was viable, so that part of the concept remained. Ideas about interface design and defining what a “powerful” editor is─ ctor As for the interface, I never I especially didn’t like that you couldn’t write without patterns, but I still wanted to do Bintracker available for composers accustomed to the traditional approach with patte─ rnami and warrant. Therefore, Bintracker must be under─ keep both approaches.I also came to you─ water that ultimately none of these will not completely solve the problem, namely: the order annoying because it makes the musician─ to interrupt the creative flow in order to deal with technical details. On the other hand hand, in the absence of a warrant it is more difficult to determine the general structure of the work. Bye these problems have not been solved, I think it’s worth pro─ continue experimenting with the tracker interface─ catfish AndBintrackershouldprovide in─ opportunity for such experiments. Regarding "power", the main stone plugins became a stumbling block. Not plugins sense of sound engine plugins, and plugins─ us for the tracker itself. Plugin Interface should allow you to save the kernelBintracker quite compact, but unlimited expand it with new and sophisticated functions─ tions. Do you want graphic editing with piano roll and envelopes? Do you want the library─ ku for storing fragments of melodies and music─ swarms of tools? What about the controls? projects with version control so that you can was to roll back to the previous version, not digging through a bunch of backup files? Or what about live online collaboration? I I think that a powerful chiptune editor should support such things. Another thing I often stay on is poured in. We basically perceive three─ ker as a kind of electronic editor tables for music, so we think about but─ tah, patterns and order as data. Od─ However, we can think of them as scripts: list of instructions that are executed by mu─ musical engine (for example, "play note X for Y ticks" ). In this sense, three─ kers become the medium of audiovisual programming.Writing music in tr─ Kere is programming. Many powerful programming languages have the ability to which is called metaprogramming. Instead of writing the code itself, in meta─ in programming you write code that writes code. The question is, how does this relate to the writing music? I think it's an open question for now, one of the possible answers to this is algorithmic composition. Algorithmics─ which composition is not particularly popular among eight-bit composers, but she became─ is becoming increasingly popular in the wider community─ versity of hackers. So algorithm support─ ical composition in Bintracker can introduce─ you bring a fresh stream into the scene, and it should be good.Bintrackercan also benefit from this, because people doing algo─ rhythmic composition, they usually know how to to gram and may be interested in programming theBintracker itself,if not The transition will be quite smooth. So, in essence,Bintrackershould be "hackable" "em". Sounds great, but how? Let's talk briefly about technologies and stack technologies used inBintracker. The most interesting technology is, of course─ Of course, the compilerMDAL,which generates─ This is the result from the engine description in the format MDEF and a module in the formatMMOD.Because data structures of existing and future sound engines vary greatly, the main thing is The main task was to create a common abstraction that could represent all varieties. The details are still being finalized─ exist, but the overall structure has already become stable─ line. MDEF consists of three main elements─ ments: input nodes, output nodes and commands. Input nodes define the input format pattern─ mat MMOD. There are 3 types of input nodes: groups, fields and blocks.Field - the main unit─ value representing a single value any type.Blocks - two-dimensional mass─ sow fields. A block can represent such structures such as patterns, orders, tables or samples.Group - recursive structure─ ra, it can contain fields,blocks and others─ gee groups. This allows you to create vlo─ related structures, for example,Module -> Song -> Patterns. By default, nodes can have unlimited number of copies, cro─ me groups that are always unique. All included─ These nodes MDEF are parts of the implicit global node (group), forming a tree. Field types are determined by commands. Yes several types of commands: String (use─ is used to represent title type texts and the author of the composition), Trigger (uses─ for reel type events by clicking in engine Huby or launching the envelope in SID ), Reference (numeric reference to another group─ pu, for example, on a pattern in an order or ins─ trument in the pattern), Label (used to indicate the location in the block instance, on─ example, loop point), Int and Uint (signed and unsigned integer arbitrary─ size, can also store logical values), as well asKeyandUkey,representing─ containing signed and unsigned key pairs, meaning. TheKey andUkey commands can have associated commandsModifierwhich contain an arithmetic operator and integers─ measured value corresponding to the range─ Well, the command values Key / Ukey. Please note Please note that there is no "note" type: notes descriptions─ are available through typeUkey,possibly with modification─ Cators for implementing detuning.MDAL usually doesn't care about the function of the command or input node, he only cares about his ti─ ne. However, commands and input nodes may have an arbitrary number of flags, and this mechanism, for example, can communicate Bintracker,should be considered by─ le with the command Ukey likenote or something more. The entire tree of input nodes is contained in implicit global node. The astute reader may have replaced─ til I didn't talk much about the warrant when mentioned input nodes. Entry order is given implicitly, its definition is created automatically by the compilerMDAL (it can be configure to enable additional fields for transposition and the like─ noe). The entry order is always matri─ purpose: each channel/track in a block has a separate track in the order, and stalemate numbers─ turns in different channels do not intersect. Since input blocks by definition have unlimited length, the order also contains a track of length that is set─ determines the length of each step. Besides this, op─ der - also a regular input node like "block". The input nodes are sparse, that is, instance Node lars are not created until they are completed will achieve, and instances of nodes, the meaning of which─ Some are not installed by the user, have value NULL.What happens when you turn─ connection to such a non-existent node depends from the requester, the node type and, in case of fields, depending on the type of command. For T nodes─ pa "group" and "block", if the requested ek─ node instance does not exist, it is created and initialized as empty. This way─ zom when the user enters the phone number─turn, which is not in the order, then this stalemate─ the turn is automatically created as a new pot─ stop knot. When the user then enters─ dit, say, a note in the eighth line, eczema─ fields of fields up to and including line 8 cos─ are given and set toNULL,and in the field, which I just edited favorably─ operator, what he entered is recorded. Kog─ yes, the compiler requests the block field, but which has the valueNULL,it depends on field commands: either the reverse will be performed─ new tracing to find the last whisker─ the given value, or there will be a value default. Output nodes are somewhat more complicated. In the present─ There are currently 6 types of output nodes. Osymbols work like labels in assembler that is, they either take the value of the current addresses are either explicitly assigned.Ofields - single integer values of arbitrary size.Oblocks - block data arrays, equivalent to input blocks. They consist from Ofields.Ogroups contain Oblocks and Ofields.They can generate orders which, in turn, are used by bonds─ lami Oorder to create the actual order─ dera. Finally, the Oasm nodes represent co─ fight bare assembly code. For example, in such a node may contain the player code. CompilerMDALintegrates with assembly─ rum, that is, the assembler can see the definition dividing level symbolsMDAL,andMDALcan keep track of the current address in assembler. Oasm nodes can be completely pre─ strictly assembled (that is, the output code is created in advance) or can be used─ write partially evaluated expressions if assembly code depends on symbols, op─ allocated at the levelMDAL. From these definitions, the compiler MDAL co─ creates a parser that reads modules.mmod into the internal pre─setting and generating the compiler, specifics─ appropriate for this configuration MDEF. Therefore compilerMDAL - this is actually not the case─ compiler, and the compiler is a compiler. Ispo─ Using a custom compiler speeds up compilationMMOD.According to the general concept, the structure The input structure is completely virtual and can be designed as a logical representation─ deletion of module elements, and not in accordance─ vii with the output structure. Thus, usually separate blocks are assigned for each channel, even if in the output structure combined patterns from all channels, and will not install fixed length for input blocks, even if the output nodes must be fixed─ fixed length - except when it is important (wave tables come to mind). When it comes to the tech stack, many from the fantasy wish list items from the previous section, drones became possible Thanks to the languageSchemeand its used re─ implementations: Chicken Scheme . Chicken Scheme can work both as an interpreter and as compiler (with a powerful external interface functions forinteraction with code in C ). This means that time-critical parts kernels can be accelerated by compilation, and extensions are interpreted, and for them startup does not require recompilation. Having built the interpreter intoBintracker,we gained the ability to metaprogram practically free. And this does not apply only for creating music: all Bintracker can be programmed at runtime. In factBintrackeris not a tracker. This is an interpreter for the language Scheme,which launches the tracker application. Since it was clear that writing emulators for each supported board─ forms are not the point, it was planned to use callMAME as the server part of the emulation, with the ability to support other emulators later. So far, MAMEhas a pretty bad reputation─ tion regarding the accuracy of the emulation, but how I think the situation has improved significantly over the past recent years, and emulation of many questions─ damaged platforms are now not inferior to special ones─ socialized emulators. Any programmer who has everdealt with native interface development─ tkoy knows that all GUI libraries are from─ wait. In the end I settled on the one which for me sucks the least. She's almost as old as our favorites 8-bit machines, written in a language that even weirder thanScheme,but it almost works everywhere, and it's called "Tk". Yes, I know: now at least half of you, respect─ self-proclaimed programmers are probably running around with screams. The rest probably can’t stand it─ Please see the source code. Current state and future of Bintracker The last two years have been serious for me─ a significant test, since I am constantly ra─ I'm working on this project without having the opportunity─ you have nothing to show. Fortunately, it's now things are getting better. I've released the source code at the end of May, so you can take a chance on─ try Bintracker in its current, early alpha stages. Until then you have to do it yourself compile and you're probably better off have for this Linux (but WSL2 should also work). Although by the time you leave─ children this number Info Guide,I may I'll get to creating assembliesunderWindows.This one of the first points in my plan. In love─ In any case, at the momentBintracker comes with several different engines─ mi under the Spectrum beeper, and also nearby engines for more exotic platforms. B I'm currently working on support Atari 2600,which means that later I can switch to to many other platforms based on 6502. Metaprogramming is fully implemented─ tew, although somewhat awkward, in the term─ le interpreterScheme.Not already available─ how many examples of simple plugins. There are still a few important details missing─ lei. Compiler MDAL does not optimize yet output data, that is, the bi created by it Nar files are longer than they could be. Something is missing in the implementationMDAL, which limits the set of sound engines, which at this stage can support Bintracker. Another detail that is not enough, regarding the order: support now─ onlyorder in the form of a matrix (by pattern for each channel, and for all sra─ zu, as inXMorVortex Tracker ). I'm planning─ It is possible to implement two levels of abstraction top: mode with a single order and mode without orders (like 1tracker ). Moreover, how mentioned above, not executable yet assemblies. And, of course, there is much more in the program glitches. As soon as I deal with them, you─ The official beta version is running. According to my races─ I guess it will probably happen later in the fall. In the meantime, check out the project at https://bintracker.org.There you can also─ please subscribe to our newsletter about Bintracker, if you want to receive the latest news about the project.
Share your thoughts about the article