More modular code would not suck, part 61824

Due to the ever-so-convenient method of writing ad-hoc code, HourGlass currently handles writing audio files when it renders like this :

The rendering code renders audio from the audio mixer and the results are passed to a function in the libsndfile library to write the buffer of audio rendered. Easy enough and works. However, if I needed to support audio file formats not supported by libsndfile or even wanted to drop using libsndfile (not likely, but who knows…), this type of arrangement would quickly start to suck. It would look like this if I wanted to add new formats not supported by libsndfile :

The rendering code would now need to know the details of each of these 4 ways to write audio files (which are completely different in this illustrative scenario). This clearly isn’t acceptable. The code really needs to be something like this :

The rendering code would only interface with a module (a C++ class, really) that can internally do whatever it has to, to implement the actual writing of the files. Of course this kind of design is more complicated to implement in code and the justification to do such a more complex design hasn’t existed yet. (While it clearly would be more future-safe.)

This is just a technical ranting/reminder to myself, not a commitment that HourGlass would support wavpack or mp3 or Monkey’s Audio files in the future. (I don’t even see how mp3 or Monkey’s Audio really would be useful, but perhaps wavpack could be…) These same points of course also apply to reading audio files for use in HourGlass, as well as the live output recording to an audio file.

This entry was posted in Uncategorized. Bookmark the permalink.

4 Responses to More modular code would not suck, part 61824

  1. Casey Basichis says:

    Thanks for posting this. I’m hauling ass trying to get my code moved over to C++ from JS. My thought is that during my composing season for work, it will be much easier to maintain and elaborate on some nice clean oop code than continuing wrestling simulated nested data structures in JS’s array.

    In getting acquainted with classes, I feel like I have a handle on how musical and audio functional aspects of the code would be implemented, but I fear that there are a whole raft of classes related to my programmer centric tasks like scheduling etc that I have no idea about. I used to do a bit of ugen coding in Supercollider and it always seems like there were endless classes most of which didn’t seem immediately audio/music related.

    It is my plan to run everything in the block loop as I do in JS, but I would really appreciate any insights into the more nebulous parts that go into making music software in conjunction with a library like WDL. Aside from the obvious musical functions and what comes for free with a library like WDL, what are the main components of a typical music program/sequencer?

    Am I over thinking this?

    • xenakios says:

      Well, it’s a complicated topic and there is no simple answer. How much you want to invest into to the code design depends on how important it is to be able to maintain and expand the code later. If you get something working once and there is no or nearly no reason to touch the code later, thinking about the things more deeply might not pay off much. Incidentally it has seemed to me that apart from monsters like NI Kontakt, plugins hardly ever evolve much during their lifetime. But even if a plugin would remain much as it is at it’s release stage, there are of course considerations of being able to reuse code in other plugins that was written earlier.

      Some main components to consider in something like HourGlass are :

      -Audio file I/O. If you write your own, you will waste a lot of time and effort on it. Already something like wav-files is a huge pain in the ass to implement. If you depend on operating system services for this, the files you can support are going to be different between each operating system, which is a pain for the user. (The available support might also depend on what codecs the user has installed on his computer.) So use something that already exists that can deal with enough formats and in a cross platform manner.

      -Audio hardware I/O (ie how the audio hardware is accessed to be able to hear and record sounds in “realtime”. HourGlass doesn’t do the latter of course but it’s fairly similar to the audio playback case how it would be handled.)

      -GUI. This should IMHO be handled by a library that is as painless as possible. Don’t write your own, it will be a huge time and effort waster and will suck anyway. Qt has been a fine choice for me for standalone apps. It is not as good for plugins, unfortunately.

      -Data persistence. This means things like saving/loading document files and undo/redo(*) and presets. ideally somekind of unified approach to this would be recommended. For example in HourGlass, many classes have methods called saveStateToMap() and restoreStateFromMap(). The classes don’t necessarily relate to each other via inheritance though, but they use a similar approach to handling their persistence.

      -Multithreading. Audio apps and plugins have to deal with multithreading pretty much by necessity, so don’t even bother thinking about things running only sequentially (1 thread/CPU core). Try to make things first so that shared resources can be thread protected at least by coarse grained locks easily. Fancier protection schemes can come later if required. Multithreading is also essential to access the full processing power of modern multicore CPUs.

      So here’s just a few points, I am not sure if this was so coherent and useful. Perhaps you might have some more spesific question?

      (*) Undo/redo can also be implemented with the so called command pattern, but I have gradually come to think that’s not a good solution for something like audio production applications. The command pattern assumes each undoable/redoable action by the user would be it’s own class. Now, look at the actions list in something like Reaper. Do you think it would be feasible to have a class in the code for each of those…? 😉 No, the Cockos developers didn’t think so either, so Reaper doesn’t use the command pattern for it’s undo/redo.

      • Casey Basichis says:

        That was very helpful. Thank you for such an extensive answer there are so many leads here to get started with. This answers so many long standing questions.

        I am combining many JS plugins into a single VST in the short term, to serve as a unified replacement to my many midi JS scoring tools, with the aim of extending it into a fully featured iOS music tool over time. This should be possible with the WDL-OL but the plugin will definitely see extreme changes as it progresses unlike most vsts. As I compose I am constantly adding new features to my JS code which is very dangerous and JS feels like a very unsafe environment as bugs are often not apparent and only reveal themselves on the deadline night of a score (this has happened scores of times)

        I’m checking out Maximilian and Gamma tonight to see if they might ease the DSP aspects for the iOS bit since I’m more interested in composing approaches than sound quality advancements.

        Thank you again. I will happily donate a bit tonight as a thank you for you help and software.

  2. xenakios says:

    It seems like a good idea to migrate complicated Jesusonic code over to a C++ codebase if you are able to, so I wish you luck and success with that! Jesusonic sure isn’t the greatest language to maintain more complicated systems… 😉

    I am not an IPlug/iOs etc expert but if you have further questions, I can probably pop in the Cockos WDL/IPlug forum and try to help. I am not a complete newbie with the IPlug stuff and I do use some of the things in WDL in my own code, so I can probably be of some help.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s