19 ms·
Four common mistakes in audio development
- amelius 10y ago> If it doesn’t, the buffer runs dry, and the user hears a nasty glitch or crackle: that’s the hard transition from audio, to silence. It would be awesome if we could prevent this crackle somehow on a lower level of abstraction. What I mean by that is that if the buffer runs dry, the hardware (or the OS/audio driver) could do some prediction in order to bridge any gaps in the audio more nicely.
- Kliment 10y agoA lot of audio hardware does this - it switches the audio off only when the signal is at a zero crossing. So it can be implemented by the OS by telling the codec that the zero value is an underrun rather than a desired signal.
- amelius 10y agoInteresting. So what would happen if a sine wave of, say, 1Khz is suddenly shut off by a buffer underrun?
- cyphar 10y agoIt would be cool if the hardware did some Fourier analysis to resample the buffers it gets (so it could make them run for longer if the buffers run dry), but it probably would cause some kind of latency issue. I reckon that just avoiding buffer underruns is less overhead.
- Bromskloss 10y agoI had to cut off an audio file abruptly once, and I found that I could smooth out the abruptness by quickly fading in a reverberated version of the audio, just as the original audio was about to end, and then letting it ring for a fraction of a second after the original had ended. (I say "fading in", but it might have been that I had the reverb applied but dry, and transitioned to wet just before the signal ended.)
- dankoss 10y agoA colleague of mine actually patented this technique: http://www.google.com/patents/US8538038 http://www.google.com/patents/US8538038
- Bromskloss 10y ago:-/
- aserafini 10y agoYep, this should not be a patent..It's a trivial solution to the problem that could be devised by any sound engineer!
- cyphar 10y agoIf you have any evidence of prior work to that patent (I really hope you do), then you can topple that patent. If your code to do what you said isn't free software I'd recommend you release it as free software now.
- Bromskloss 10y agoI can't check right now, but it's possible that the patent predates my use of the technique. Even if not, I don't know how I could prove it. By the way, it wasn't done in code; I did it manually in Ardour [0]. [0] <https://ardour.org/> https://ardour.org/>
- deleted 10y ago[deleted]
- amelius 10y agoThis seems like the most sensible thing to do, and was actually what I was getting at :) What do you mean by latency issues? Why would there be any?
- JonnieCache 10y agoQuoting from the Waldorf microwave XT synthesizer FAQ: The brightness of the click depends on the speed of the level change. The faster the level changes, the brighter is the click. So, the level change speed can be compared with the cutoff of a lowpass filter. There is an easy formula for it: Let's consider a level change from full to zero (or from zero to full) output from one sample to another on a machine that uses 44.1kHz sample rate. So, we first transfer the sample to milli seconds: 1 sample equals 1/44100 second, which is = 0.02267573696ms. To calculate the cutoff frequency of the click, just use this formula: Cutoff (Hz) = 1000 / Level Change Time (ms) which in the example results in: 44100Hz = 1000 / 0.02267573696ms Whoops? This the sampling frequency and, err, very bright. http://faq.waldorfian.info/faq-browse.php?product=xt#116 http://faq.waldorfian.info/faq-browse.php?product=xt#116
- blt 10y agoWaldorf seems like a cool company. It makes me smile to see that they went into such detail in the manual. Plus the Microwave XT sounds amazing.
- Kliment 10y agoWith zero crossing detection, it would need to know the buffer is running out before the next zero crossing occurs. So if the shutdown signal is given within the last millisecond before the zero crossing, it would ignore all data that comes after the zero, and output zero for the remaining partial wave. On starting up again, it would wait until the signal is at zero before beginning to output. At least that's how the common audio codecs I've seen that implement that feature work. The most common application is volume control, where you don't want a sudden change in the amplitude of the wave to result in a glitch, so you adjust amplitude at zero crossings.
- deleted 10y ago[deleted]
- deleted 10y ago[deleted]
- buserror 10y agoI solved that problem years ago by keeping a canned piece of white noise in a const buffer that I would switch to if there was an underrun, with an immediate ramped gain reduction to zero. The result were quite good!
- JonnieCache 10y agoIts certainly true that different hardware handles buffer underruns differently, my high-quality RME interface emits fairly muted pops when the buffer runs dry, whereas I've had cheaper units make absolutely horrendous noises as the speakers flail around trying to cope with the signal discontinuities. The RME is interpolating the signal towards a zero crossing.
- Bromskloss 10y agoWould it be even better to smoothly join with the zero level instead of coming to a sudden halt?
- JonnieCache 10y agoThat's what I mean by interpolating towards a zero crossing.
- Bromskloss 10y agoSorry, my wording was unclear. I mean asymptotically approaching zero, as opposed to, say, going to zero in a straight line and then switching to a constant zero once you get there (thereby creating a discontinuous derivative).
- enneff 10y agoThat's not how sound works. Think of a vibrating object. If it stops vibrating suddenly, slowly moving it to its center point isn't going to make the absence of vibration any less jarring.
- JonnieCache 10y agoIndeed. I think that's what I'm trying to describe in my sibling comment to yours. However, what it will successfully avoid is the loudspeaker driver attempting to instantaneously snap from some nonzero x-position back to it's origin, which is what causes the really nasty clicks.
- enqk 10y agoSome network protocols for live audio performances do this. Filling the audio buffers with some predicted blocks of audio to avoid an ugly sounding gap. See for instance in this Thesis: "Low-Latency Audio over IP on embedded IP systems" http://www.ti5.tu-harburg.de/staff/meier/master/meier_audio_over_ip_embedded.pdf http://www.ti5.tu-harburg.de/staff/meier/master/meier_audio_... Sect 4.1.2 Packet Loss Handling
- enneff 10y agoUltimately it's not solving anything, because even with some faking it's still not the audio the performer wants to hear. And, besides, gap-free audio software is a solved problem. The article explains how to do it.
- exDM69 10y ago> It can be helpful to know that, on all modern processors, you can safety assign a value to a int, double, float, bool, BOOL or pointer variable on one thread, and read it on a different thread without worrying about tearing This is true on the CPU side (for some CPUs) but what about compiler optimizations? Using "volatile" should make stores and loads happen where they are written in the code, but can it be relied on in multi threaded use cases? It's generally frowned upon for a good reason, but perhaps it's acceptable if you're targetting a limited range of CPUs (the article seems to be focused on iOS and ARM only). A safer bet would be to use __atomic_load and __atomic_store (from [0] or [1]) or C11 atomics if you have the appropriate headers for your platform. They provide safe loads and stores for all CPU architectures, and provide the appropriate memory barriers for cache coherency (for architectures that do care). [0] https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html#g_t_005f_005fatomic-Builtins https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins... [1] http://clang.llvm.org/docs/LanguageExtensions.html#langext-c11-atomic http://clang.llvm.org/docs/LanguageExtensions.html#langext-c...
- Bromskloss 10y agoDo you mean that a compiler optimisation could cause tearing of the mentioned data types? That's surprising to me and I'd like to know more about it.
- _pmf_ 10y agoI think the extreme case would be a packed struct where a multibyte member happens to span cache lines. This would not be causedby compiler optimization, but by manual deoptimization.
- biokoda 10y agoNot tearing, but it could reorder the assignment so that it happens someplace else than you think it will. For this kind of thread synchronization memory barriers should be used at least.
- exDM69 10y ago
- bwindels 10y agoGreat article. Interesting that modifying and reading word-sized values is an atomic operation on ARM. IIRC on x86 this is not the case because values can be cached on the cache of the different cpu cores, and thus be out of sync. Does someone have a more detailed insight into this?
- biokoda 10y ago> and thus be out of sync The operation is still atomic. You will not get a partially written word size value.
- AstralStorm 10y agoARMv7 works on deferred consistency between cores and memory. So, even if the write itself is "atomic", which should rather be called tear-free, there is no inherent synchronisation of writes and reads to the same memory location. C11 and C++11 atomics also guarantee ordering depending on the memory model parameter. Look up Sutter's talk titled "Atomic Weapons" for more detail.
- bwindels 10y agoInteresting talk! Here's the link: https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-20...
- stplsd 10y agohttps://lagunita.stanford.edu/c4x/Engineering/CS316/asset/A_Primer_on_Memory_Consistency_and_Coherence.pdf https://lagunita.stanford.edu/c4x/Engineering/CS316/asset/A_...
- webscalist 10y agoBetter article: http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing http://www.rossbencina.com/code/real-time-audio-programming-...
- mobiuscog 10y agoI wouldn't say 'better', they're both useful.
- deleted 10y ago[deleted]
- fenomas 10y ago> Any app that does audio has at least two threads of execution: the main thread, and the audio thread As a side note, I sure wish browsers would hurry up and implement web audio workers so that this could be true for me!
- eterm 10y agoWhy don't we have have sandbox execution environments in the OS itself? Why do we have a web browser at all and not just a way of running arbitrary code from a network in a sandbox? We'll end up re-imagining the browser as an OS with workers for anything an OS could do anyway in the end if we continue to need to have the browser act as an application runner.
- vertex-four 10y ago> Why don't we have have sandbox execution environments in the OS itself? Well, if you try, you wind up with something that looks an awful lot like a web browser - especially once WebAssembly is a thing. The API that many desktop operating systems provide is not designed for the security model that you're looking for, so you wind up building a new one on top of it - see WinRT when Microsoft needed a sandbox. We used to have things like Java Web Start (still do in some enterprise systems), and, well, it's not exactly any better than a web browser except that it has a better view layer for applications than HTML/CSS. It's also not supported on mobile platforms.
- pjmlp 10y ago> Why don't we have have sandbox execution environments in the OS itself? We do, that is how mainframes work. It is also available in Mac OS X, Windows and mobile OSes, one just needs to make use of the respective APIs. As for the GNU/Linux and *BSD I am out of touch how good the current sandbox support for cnames, Lx and others actually is.
- moron4hire 10y agoIt was called Java and it never lived up to the promise. The browser may not be the app deployment system we want, but it is certainly the one we deserve
- joshkpeterson 10y agoHow will web assembly affect audio development in the browser?
- splatcollision 10y agoJust reading the intro so far, not an audio developer particularly, but wanted to quote this: > although there is a high horse present in this article, consider me standing beside it pointing at it, rather than sitting on top of it. Something we can all aspire to!
- kranner 10y agoSeneca in https://en.wikisource.org/wiki/Moral_letters_to_Lucilius/Letter_27 https://en.wikisource.org/wiki/Moral_letters_to_Lucilius/Let... "What," say you, "are you giving me advice? Indeed, have you already advised yourself, already corrected your own faults? Is this the reason why you have leisure to reform other men?" No, I am not so shameless as to undertake to cure my fellow-men when I am ill myself. I am, however, discussing with you troubles which concern us both, and sharing the remedy with you, just as if we were lying ill in the same hospital. Listen to me, therefore, as you would if I were talking to myself. I am admitting you to my inmost thoughts, and am having it out with myself, merely making use of you as my pretext.
- bartl 10y agoI'm a bit amazed he doesn't even mention [double buffering](https://en.wikipedia.org/wiki/Multiple_buffering https://en.wikipedia.org/wiki/Multiple_buffering), a system that was already used in old video games to avoid flicker, as a way to draw on scene screens and only pass it on to the video stage once the scene is complete. All you would need here is 2 (or more) copies of the shared data structure and a few pointers to the data structure. You fill in a draft version of the data structure and only change the "read" pointer to point to it when it's ready. Changing that pointer is, I would hope, atomic. You can then change the "write" pointer to point to a different copy of the data structure to work on. To make sure the client only reads consistent data, it can make a copy of that pointer before it starts processing, because the pointer itself might change. Using 3 buffers instead of 2, and if you're sure the processing of a buffer takes less time than the switching cycle time, you can be sure your buffer data will not ever change in the meantime.
- JoachimSchipper 10y agoDouble buffering isn't very suitable for audio. You're right that a suitably-large buffer would allow non-realtime code to "render" e.g. a tenth of a second of audio and pass it off to the realtime audio thread (and/or the audio subsystem, if that has sufficiently-large buffers on your platform). Unfortunately, such large buffers also introduces significant latency; the added latency is fine if you're a music player, but is pretty nasty for interactive applications.
- squeaky-clean 10y agoThe audio doesn't need to be double buffered. I think GP means you can avoid the author's examples with locks by double buffering the array of keyboard keys being pressed. You don't need to lock either the UI or audio thread, and can ensure they're both seeing uncorrupted data.
- SonOfLilit 10y agoBut he does, under another name...
- leddt 10y ago
- cageface 10y agoI spent the better part of the last few years working on my own audio apps. It's definitely the most difficult programming domain I've worked in. Real time requirements + threading + low level code makes for a very challenging environment. But it's also a lot of fun. Using the tools the author describes here can save you a lot of headaches and let you focus more on the fun part though.
- benwad 10y agoSince we seem to have a lot of audio programmers in here, does anyone have an opinion on using non-C/C++ languages for audio development? I've always used C/C++ but newer systems languages like Go and Rust (both have e.g. PortAudio support) seem quite well suited to the task.
- wrl 10y agoSo, I mostly use C (not C++) for my audio code. I won't touch anything garbage collected for realtime DSP at all, so Go is right out. Rust, on the other hand, I am very keen to explore, especially with some of the SIMD work that's been brewing. Somebody made bindings for the VST2.4 API/SDK already, and I've been mulling over putting together a brief proof-of-concept with it: https://github.com/overdrivenpotato/rust-vst2 https://github.com/overdrivenpotato/rust-vst2
- jzwinck 10y agoGo typically relies on garbage collection, which is a no-no. Same with Java. This can be worked around, but you may find that programming a GC language with the GC unavailable is not better than C++ (and it may rule out the use of most third-party libraries). Rust at a high level could be suitable, when well-tested libraries exist for it.
- jerf 10y agoYou'd have to write in a bit of a dialect of Go to make sure you don't get bad GC behavior. It's possible in Go, unlike many scripting languages, to write in an allocate-up-front style that doesn't generate garbage, in pretty much exactly the same way you'd do it in C. If you write in the C style, you get a lot of C-like behavior, only with memory-safety. But you don't get much support from the runtime for this style; for instance, if you accidentally append to a slice beyond its capacity, the runtime will simply reallocate the array, there's no way to ask it to not do that and throw an error instead or something, beyond not using "append" (hence my comment about the "dialect"). ('Course, there isn't really one in C either; arguably reallocation is better than a segfault here, as one merely risks an audio pop at some point whereas another guarantees it.) There is also no way to prioritize a goroutine. I think people end up overselling the difficulty here, because people often strike me as speaking as if the 10ms maximum GC delay is actually the minimum or something and as if the GC is running uncontrollably keyed by a random number generator or something, rather than the amount of garbage generated. It's not that hard to imagine an audio application that runs a 50us GC every several minutes or even less often if you preallocate everything. In practice it's not entirely dissimilar to writing in C and avoiding malloc. But the real level of difficulty is still something that should make you think, especially as you move from "a single filter" to "a full synthesizer suite". Rust would generally be a better language, as long as you can step up to the somewhat-harder language, and can find the libraries you need. The payoff for the somewhat-harder language is that you'll have much better assurances about many of the relevant issues. It's what I would generally choose for this task, again, given libraries. But if someone did want to use Go because it's a bit simpler of a language, I wouldn't immediately breath flames on them, unless they were being obviously too ambitious.
- aidos 10y ago> It can take just one glitch during a live performance for a musician to completely lose faith in their whole setup I was an early adopter of digital vinyl (if you haven't seen it before, the records have a screechy signal that software can use to determine the position of the needle on the record, which it then maps to an audio file). A friend of mine purchased the most popular unit at the time but it was really unreliable. It crashed once while a club full of people were dancing and that was the end of it for me. I switched to a unit by a small company (Serato) that had just been released (2004) and never looked back. The unit itself still works perfectly, there was a bug back in about 2008 that they tracked down and patched for me. Apparently the original brand has now caught up technology-wise and they're a big player, but I will never, ever, ever buy their kit. Reliability issues with audio gear can completely destroy your trust.
- Unklejoe 10y agoI saw a DJ using one of those digital encoded records a few weeks ago. Pretty cool concept, although I'm not sure what the actual difference is between that and using something like Serato which has the smaller wheels you can turn (if I remember correctly), other than being more prone to physical damage. I guess one advantage is that it looks like they're playing the actual records. It had me fooled for a minute.
- aidos 10y agoHaha, to be fair - they are playing actual records :) At the time neither the tech nor acceptance were there for the modern tools. While increasingly there were CDJs around, they didn't feel the same for people who did any scratching. Also, turntables were everywhere you went, so you could take everything you needed in your bag (laptop, 2 x records, little conversion box) and you could just plug into an existing setup, anywhere, without issue. Digital vinyl bridged the gap as people started moving over. Also, at the time the software only worked with records and cds. Now you have a huge selection of controllers to choose from. I'm actually about to sell all my stuff to buy a "controller" (something like https://www.google.co.uk/search?q=reloop+terminal+mix+8&tbm=isch https://www.google.co.uk/search?q=reloop+terminal+mix+8&tbm=...) so that I have something convenient and always ready to go.
- iammyIP 10y agoThese mistakes basically boil down to not using slow scripting languages and making the core buffer loop run fast and undisturbed. For realtime synthesis use c or c++, optimise early, use trigonometry approximations in range -pi / pi, do not use lookup tables, they unnecessarily fill the cache, cpus are fast enough, write the core loop branchless, write for cache, use vectorisation and function pointers. Do not use anything fancy, simple int32_t, float and vector/array is enough (some filters need double precision though). Do not copy stuff, point to it. Precalculate what can be precalculated, e.g. dont do x / samplerate, do x * samplerate_inverse. Check for denormals.
- Unklejoe 10y ago[do not use lookup tables, they unnecessarily fill the cache...] Good point. A major misconception that a lot of people have is that lookup tables are always faster than actually calculating a value, but cache locality is usually not given as much attention.
- cesarb 10y agoIt used to be true in the past. Back then, processors were slower, and they had no cache, since the processor and memory speeds were roughly matched. A few integer multiplications would be enough to cost more than a single memory access. It should still hold true today for small embedded processors with slow arithmetic and no cache.
- beached_whale 10y agoThey often lack ram too, so that const lookup table could be sitting on flash.
- davedx 10y agoThat's not my takeaway from the article. It's not saying don't use "slow scripting languages", it's saying avoid language features that are not safe for real-time programming and give the audio thread enough time to do its thing. In my experience, writing everything in C/C++ has its own host of problems. What's worse, a GC stutter or a segfault? :)
- dmytroi 10y agoI really love time restricted environments, in my opinion they truly liberate programmers: instead of using language/library/tech/pattern/etc-of-choice they suddenly realize "oh, we don't have time for that". Do we need GC? We don't have time for that. Do we need to allocate memory? We don't have time for that. Can we maybe do this enterprise-like tens thousands source code files OOP hierarchy thing? We don't have time for that. Realtime forces people write less, writing only what actually matters, and all this in my opinion helps people to be better engineers (in-a-way). I just wish it looked more attractable for people - hacking your way out in time/resources constrained systems (like MCU's for example) can be as fun as hacking html/js to make your site behave as you want.
- davedx 10y agoIf only that was what actually happened... I spent a few years working in the games industry, and let me tell you, enterprise-like tens of thousands of lines of code files with massive OOP hierarchies were all too common. That's why I think Unity3D is fantastic -- they do the OO (composition) in their engine libs, you write simple scripts. In my experience, what really forces people to write more code "that matters" is programming languages and frameworks that constrain them.
- dmytroi 10y agoI also work in gaming industry and IMHO it depends on games, usually the biggest fun is on consoles market, people start making AAA games with engines like Unity, Unreal Engine 3/4, Autodesk Stingray (recently was bitsquid) and then they suddenly realize "oh, we are not getting 30 fps here, because of Lua/C++/etc" and then the fun starts: IIRC one game company was even asking Microsoft to add missing intrinsics to xbox one compiler because they were used in PS4 code, and PS4 and X1 are basically almost the same chip :)
- davedx 10y agoyeah. The biggest, ugliest C++ code bases I've seen were for AAA games. Some of the best programmers work in games, but you also see lots of grads and staff churn. TBH I have never seen a big C++ code base I liked. Unity may have its detractors and genuine deficiencies but the Unity projects I worked on were much more maintainable due to the constraints of working inside Unity itself.
- zongitsrinzler 10y agoWhat song is it in the 4sec sound clip. Sounds so familiar, like something from Daft Punk?
- emiliobumachar 10y agoSo, I assume none of those popular OS'es has priority inheritance[1]. Even though it's a concept from realtime computing, I though it would be widespread in general-purpose OS'es as well. Really, it seems like a useful feature for any OS that implements priority at all. What would be the downsides of having it in a general-purpose OS? The ones I can think of are development cost and processing overhead. [1] https://en.wikipedia.org/wiki/Priority_inheritance https://en.wikipedia.org/wiki/Priority_inheritance
- fl0wenol 10y agoIt's available, but the concept has issues when implemented simplistically on a multi-processor system. (I'm not familiar with the arguments as to why; sorry). You also have to request this behavior explicitly, and I think under certain circumstances it can add latency or additional context switching overhead that might otherwise be avoided between your application threads. Also, in some environments your application has to have elevated privileges to boost thread priority, which carries risk.
- camperman 10y agoI remember using a circular buffer for a MOD/S3M player I wrote many moons ago. I think you called a hardware interrupt to enable the Gravis or Soundblaster to read from a block of memory and send it out to the speakers at the right frequency, and then made sure that you fed enough data into the buffer. It wasn't even concurrent - every loop, just mix enough of the track to fill the buffer and write it. Simpler days...
- exDM69 10y ago> It wasn't even concurrent - every loop, just mix enough of the track to fill the buffer and write it. This probably works but the proper way to do it back then (and the way drivers work today) was to hook an interrupt that gets fired when the audio buffer needs to be filled. So there's an element of concurrency in it since you don't know when the IRQ is going to fire. Synchronization was easier with single cores, though. Just disable interrupts and you're done.
- camperman 10y ago> This probably works No probably about it - it worked like a charm. > but the proper way to do it back then (and the way drivers work today) was to hook an interrupt that gets fired when the audio buffer needs to be filled. Which was much more trouble than it was worth when writing a 64k intro on a deadline.
- deleted 10y ago[deleted]
- tantalor 10y agoThis is also true of animation threads.
- deleted 10y ago[deleted]
- ukyrgf 10y agoI wasn't even aware I WAS living in a "post-Audiobus/IAA world". So these are... iPhone apps?
- pierrec 10y agoYeah, the article reads like it's going to be somewhat platform-agnostic until you're down a few paragraphs and it blasts you with iOS stuff as if it was the only platform that mattered for realtime audio. I'm more of a mind that realtime creative audio on iOS is likely to be remain pretty niche.
- delinka 10y ago"Don’t use Objective-C/Swift on the audio thread." Nothing wrong with using Swift (the language) to render audio in realtime on the audio thread. I'd change the advice above to: don't send messages to Objective-C objects during your audio thread.
- callesgg 10y agoSwift will need to do garbage collection at one time or another and then you are fu*ed.
- plorkyeran 10y agoSwift is reference counted and does not pause at unpredictable times.
- deleted 10y ago[deleted]
- vardump 10y agoReference counting is a form of garbage collection. You can have avalanches of objects being deallocated when as a consequence of one object refcount reaching 0. You don't want any allocation or deallocation when you need realtime performance.
- plorkyeran 10y agoAn object's refcount being decremented is not an unpredictable time for a pause. If you never allocate or release objects on your audio worker thread, it will never be paused for GC, as the person I was replying to implied could happen.
- vardump 10y agoSure. But same can be said for pretty much any garbage collected system. If you don't create objects or cause objects to become unreachable, you also won't be creating garbage. So you won't have GC pauses. Unless the GC system is braindead and runs even when there's no heap pressure.
- radarsat1 10y agoOr just use FAUST: http://faudiostream.sf.net/ http://faudiostream.sf.net/ Seriously, check it out, it's awesome. Write your audio DSP in a language suited to it, compile to efficient C++ (among other languages) and optionally embed it in a (huge) variety of environments. (even Javascript for webaudio) It's a functional description language that describes a DSP graph, and can generate block diagrams too. Not to mention, it has libraries containing any filter you can imagine. Highly recommended.
- Ace17 10y agoFAUST definitely is worth checking out. Its authors are concerned with "long-term preservation of music programs", which is a great idea ; FAUST allows you to do just that. One can write audio dsp code, without cluttering the actual audio computation code with implementation/performance stuff like SSE, VST, ... that will be obsolete one day. Another key point is that FAUST doesn't let you manipulate individual samples or time, but instead, focuses on the dataflow, which means you don't have to start all your programs by a time loop ; for example, a simple 2-input mixer is just "process = +;". It's a huge improvement over "for(t=0;t < n;t++) out[t] = in1[t] + in1[t];".
- mhroth 10y agoYou can do something similar (translate to fast C) with Pure Data (Pd) [0], a graphical audio programming language, by using Heavy [1]. [0] http://puredata.info/ http://puredata.info/ [1] https://enzienaudio.com/ https://enzienaudio.com/
- radarsat1 10y agoCool, I hadn't heard of Heavy. It had me until "use our cloud-based service to instantly generate high-performance code for x86 and ARM platforms." The day I switch to using a hosted service to compile my code... Still, nice idea.
- gradinafrica 10y agoThe Firefly references in this article are on point.
- JoeAltmaier 10y agoAnother common mistake: off-by-one error. Even a single zero or duplicate sample value is clearly audible! Its amazing how sensitive we are to audio artifacts.
- iammyIP 10y agoThat's not necessarily a off-by-one error, but a broader problem of audio synthesis, which you can generally deal with by applying low pass filtering. For example depending on starting phase of a sinus oscillator multiplied by a simple linear volume envelope (1.0 -> 0.0) you will get a click at the first sample, which is loudest at multiples of pi/2 for the starting phase (cos). So you need to low pass filter the envelope to get a quick fade-in of the oscillator without click. How you do this and how that sounds is up to you. The original hammond organ similarly got some nice analogue clicks as initial transients because of this 'problem' as a side effect btw, in digital its much harder and expensive to make nice curves. De-clicking an audio engine properly is certainly an important and sometimes frustrating task.
- sehugg 10y agoIt kills me that it's 2016 and pulseaudio stutters when I move a window (at least on my system).