A wavetable based synthesizer TRABAJO FIN DE GRADO CURSO 2020-2021 AUTHORS Adrián Melero Moreno Izan Bravo Fernández SUPERVISOR Miguel Gómez-Zamalloa Gil TRABAJO FIN DE GRADO FACULTAD DE INFORMÁTICA UNIVERSIDAD COMPLUTENSE DE MADRID 1 This document is distributed under license Creative Commons BY-SA 4.0. International ( CC-BY-SA-4.0 ) You are free to: ● Share — copy and redistribute the material in any medium or format ● Adapt — remix, transform, and build upon the material for any purpose, even commercially. The licensor cannot revoke these freedoms as long as you follow the license terms. Under the following terms: ● Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. ● ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 2 ACKNOWLEDGEMENTS We would like to thank the project director Miguel Gómez-Zamalloa Gil, for his help and support during the realisation of this project. We would also like to thank Professor Jaime Sánchez Hernández, who has also helped and supported us by providing another point of view. We would also like to take this opportunity to thank our loved ones who have been closely following the evolution of our final project. 3 RESUMEN Hoy en día hay una amplia variedad de aplicaciones dedicadas al mundo de la música. El espectro es grande, desde un simple efecto de delay hasta aplicaciones mucho más complejas como pueden serlo Serum o Avenger, capaces de modular sonido, crear ritmos e incluso efectos de viento o efectos completamente originales. Hemos elegido crear un sintetizador, que consiste, en su versión analógica, en un instrumento musical electrónico que recibe una serie de señales y las transforma en corriente eléctrica mediante la cual produce sonidos a través de un sistema de escuchas. Nuestro sintetizador genera desde simples ondas sinusoidales a tipos más complejos de onda, a las cuales podemos aplicar distintos efectos. Por ejemplo, podemos mezclar una onda dientes de sierra con ruido y aplicar delay al conjunto de la mezcla. El sintetizador puede ser añadido como un complemento a los programas de hoy en día que se usan en los estudios de grabación y tendrá también una versión funcional por sí sola. Nuestro programa será realizado con la ayuda de Juce, que es un marco software de código abierto que facilita y apoya la creación de herramientas musicales como la nuestra. Palabras clave Plugin, music , synthesizer, wave, signal, MIDI, DAW, instrument 4 https://www.linguee.com/english-spanish/translation/sawtooth+waveform.html ABSTRACT Nowadays there is a wide variety of applications related to the world of music. It is a very wide spectrum, from a simple delay effect, to more complex applications such as Serum or Avenger, which can do things like modulate sound, create rhythms, wind effects, or even effects of their own. We have chosen to create a Synthesizer, which consists of an electronic musical instrument that receives a series of signals, which is then used to generate electrical signals, which are converted into sound through speakers or headphones. Our synthesizer can generate from, a simple sine wave to more complex waves, to which an effect can be applied, for example a sawtooth waveform mixed with a noise wave and a delay at the same time. The synthesizer can be added as a complement to today's software used in recording studios and will also have a functional version on its own. Our programme will be realised with the help of Juce, which is an open source software framework that facilitates and supports the creation of musical tools like ours. Keywords Plugin, music , synthesizer, wave, signal, MIDI, DAW, instrument 5 https://www.linguee.com/english-spanish/translation/sawtooth+waveform.html INDEX Chapter 1 - Introduction 8 1.1 Talking about the basics 8 1.2 Motivation 9 1.3 Objectives 10 Chapter 2 - Music Concepts 11 2.1 Brief History 11 2.2 Monophony, polyphony and presets 12 2.3 Synthesis types 13 2.3.1 Subtractive synthesis 13 2.3.2 Fm synthesis 14 2.3.3 Sampled based synthesis 14 2.3.4 Wavetable synthesis 15 2.3.5 Additive synthesis 16 2.3.6 Granular synthesis 17 2.3.7 Other types of synthesis 18 2.4 About DAWs and MIDI 19 2.4.1 Daws 19 2.4.2 Midi 21 2.4.3 Midi in Daws 22 Chapter 3 – Synthesizer Manual 23 3.1 Overall features 23 3.1.1 Installation 23 3.1.2 Configuration 24 3.1.3 Basic usage 25 6 3.2 ADSR 26 3.2.1 ADSR knobs 27 3.2.2 ADSR visualizer 27 3.3 Morph 28 3.4 DSP modules 30 3.4.1 DSP Delay 30 3.4.2 DSP Reverb 31 3.4.3 DSP Filter 34 3.5 Preset Manager 36 Chapter 4 - Implementation 37 4.1 Technologies 37 4.2 Audio chain 38 4.2.1 Generating audio 38 4.2.2 About audio chain 39 4.3 Oscillators and Morph 41 4.3.1 Random rate management 44 4.4 ADSR visualizer 45 4.5 DSP modules 47 4.6 Preset manager 51 Chapter 5 - Conclusions and future work 53 5.1 Conclusions 53 5.2 Future work 53 Bibliografía 55 7 CHAPTER 1 - INTRODUCTION 1.1 Talking about the basics In this chapter we aim to give an overview of what a synthesizer is, how it works and the technologies that make it possible. It also includes an overview of the tools in which our synthesizer can be used (in this case). [1] A synthesizer is an electronic musical instrument capable of producing sounds of any frequency and intensity and combining them with harmonics, thus providing sounds of any known instrument, or sound effects that do not correspond to any conventional instrument. Now that we know what a synthesizer is, we should ask ourselves the question of how an electronic instrument can be played. And here we introduce the concept of a plugin, which is a software add-on that helps a program do something it would not normally do on its own. In general terms, we now know what a music plugin is, but we are missing the most important thing, which is to know what kind of software programs can use our project, and this is where DAWs come in, [2] DAW is an acronym for "Digital Audio Workstation". It is any digital software or device that allows you to record, edit and compose your audio tracks. Therefore it will be necessary to install a DAW program, for example REAPER [3], but we have chosen to create a standalone version, which works just as well without the need for such programs. In order to create our programme in a simpler way, we have used the help of Juce and its tool Projucer, which provides some libraries and basic structure to create our own application. 8 1.2 Motivation We believe that the ability to create music should be available to everyone, from people who can afford very high end equipment to those who have more modest tools. Taking into account that nowadays, any mid-range computer can support a DAW, we have opted for the idea of creating ourselves a synthesizer that is simple and easy to use for those individuals who are not very close to the world of music. It can also be used by people who are looking for some more advanced options. Because of this, our application is available in two versions: ● As a plugin, so that it can be used in a DAW. ● As a standalone application, for those who prefer not to use a DAW. 1.3 Objectives Our intention is that any user is able to create music. That is to say, that whoever sees our application (in any of the versions) feels that by simply pressing a button he/she can create a sound. Although it sounds contradictory, we also want our tool to attract those who already know or have had some contact with the world of music. Therefore our project will have the following key points: ● It’s going to be a simple plugin. We want our project to be a pure and simple synthesizer, without external elements that could make it seem to have a different functionality. ● Another important point is aesthetics and visuals. To be able to see graphically all the changes we want to make while composing. ● Simplicity when it comes to play with it and operate it. Being able to listen any sound by simply pressing play and tweak a few options. ● Cover all types of popular waveforms. We will have a vast repertoire of sound waves to choose from and blend them together to form new ones. 9 ● FX design is an important feature in every synthesizer. We will have some effects that will help to create additional sounds. ● A preset manager is a must in order to store patches. Who wouldn't like to be able to save their favourite combinations? ● Of course we will add a volume slider. It may seem obvious, but not all plugins have the ability to turn the volume up or down. ● Ability to manipulate some characteristics of a waveform. We've talked about there being a variety of waves, but of course these can be modified by the user through some parameters. ● Ability to sum several waves. Two are better than one, although not always, in this case if it is true, we will have two waves sounding, to be able to give more creativity (you can mute one of them). All in all, our aim is to provide a fully functional synthesizer that allows users to manipulate options easily and create new sounds, offering a pleasing experience and interface to work with. CHAPTER 2 - MUSIC CONCEPTS 2.1 Brief History We are not going to go deep into details for explaining the vast history of synthesizers, but we will cover the main historical events that led to build the first set of synthesizers. At the beginning of the last century, several academic studies and engineering inventions were the perfect mix to create the Theremin [4]. Although it was a huge breakthrough in academic terms (it was the first time humanity could generate sound without a “natural” oscillation), it didn’t evolve much in musical terms, given that the technology was still new, expensive and the machinery was too big to handle. It wasn’t until Bob Moog released the Voltage-Controlled Music Modules in the late 60’s that things got serious. He addressed the main problems synthesizers had at that time, 10 which were, as stated before, modularity (synthesizers at that time we big and complicated to handle), prices (although they were not cheap) and control over the instrument (theremins and its variants are complicated to operate). The first person to use one a synthesizer entirely in a musical work was the composer Wendy Carlos. She had great success with the LP "Switched on Bach" in 1968, with works by Johann Sebastian Bach, and was revered by the media and the public. After Moog’s breakthrough, synthesizers evolved in all directions as every technology does when you put it at people’s reach. This led to today’s advanced and tiny synthesizers, digital synthesizers as we will mention in chapter 1.1.4 , and all the different ways of synthesis that we will explain later on in this chapter. Nowadays we can assert that practically every recording has a synthesizer in it. Most tracks contain some sort of synthesised sound, it doesn’t matter if it comes in the form of an instrument emulation, new instrument created from scratch, or in the form of plain audio FX. 2.2 Monophony, polyphony and presets Monophony and polyphony are the two main features that synthesizers had along their evolution. First, when the circuitery was still complex and synthesizers as we know them today were being born in the late 60’s, monophonic synthesizers were the only option. Given that creating a single audio chain from the beginning (oscillators) to the end (it varies, depending on the modules configuration) was still very complicated, it is easy to understand that creating simultaneous oscillations for different notes was a hard task to complete. That’s the reason why the first synthesizers were monophonic (only one note could be played at a time). There was no way of storing presets. As these models were all analogue and technology was not as developed as today’s, knobs and sliders didn’t have motors 11 inside to move them automatically. This means that if you wanted to keep a preset you liked, you had to memorise or write down the current state of the synthesizer in order to go back to it. Other option was to not touch anything, but this way you get stuck playing the same preset over and over. There was no method of storing presets [5]. In the years to come, with the evolution of technology and the first CPU’s and processors, and the help of digitalization synthesizers got a way of storing these presets. The improvement of the systems led to being able to play more than one note at a time [6], giving birth to the first set of polyphonic synthesizers, such as the OB-X. 2.3 Synthesis types We have made a list of the major and most important synthesis types and how they operate. Usually a synthesizer type is defined by the way it produces sounds. 2.3.1 SUBTRACTIVE SYNTHESIS This was the first type of synthesis invented given its own simplicity. You start off with one or more oscillators producing a sound. As this sound has yet no modifications, it has a wide variety of frequencies going on at the same time, which results in a rich but at the same time very (subjectively) obnoxious sound. That’s were subtractive synthesis comes in. We can address this “problem” by using filters and volume envelopes in order to shape the sound as we please and make it more appealing. In figure 2.1 we can see the roland jupiter-8 as a great example of a subtractive synthesizer. 12 FIGURE 2.1: Roland jupiter 8 2.3.2 FM SYNTHESIS FM synthesis means Frequency Modulation synthesis. What FM synthesis is all about are carriers and modulators. Both concepts come from oscillators generating waveforms, but there’s a catch. The carrier waveform, which usually starts as a pure sine wave, is the audible part of the sound we hear. The modulators are also waveforms generated by oscillators, but we can’t hear them. Instead of making them audible, FM synthesizers use these modulators, as their name says, for modulating the carrier wave. By stacking up several of these carriers and modulators on top of each other we enlarge the complexity of the final sound which started as a simple sine wave. In figure 2.2 we can see how this works using just one carrier and one modulator, which is called Data signal. 13 FIGURE 2.2: FM modulation 2.3.3 SAMPLED BASED SYNTHESIS It’s a very widespread synthesis technique today. The synthesizer starts off with a recording of any kind. Later on, with the aid of digital manipulation of sampled recordings, the synthesizer is able to reshape that recording in several ways. This includes pitch shifting to match the original sound with the key currently pressed. It can also elongate or shorten the sample (this helps the process of pitch shifting too), and pretty much add any effect already in use for other kinds of synthesis. A very popular example of this kind of synthesizer is the AKAI MPC 2000 seen in figure 2.3 14 FIGURE 2.3: Akai MPC 2000 2.3.4 WAVETABLE SYNTHESIS Wavetable synthesis is very straightforward. We have already a set of different waveforms built in the synthesizer. What we do with them is selecting which one we want to play with a modulator. The synthesizer then tries to transition smoothly from one waveform to another (depending on the synthesizer options and how it operates internally this can be more abrupt). One of the most popular wavetable synthesizer nowadays and the one that inspired this project is Serum. We can see a 3D model of its interface in figure 2.4. 15 FIGURE 2.4: Serum VST 2.3.5 ADDITIVE SYNTHESIS This type of synthesis is very similar to subtractive synthesis, but it works the other way around. It starts with very simple sounds (usually just sine waves) that are stacked together taking into account harmonic partials of the root wave (let’s say we’re playing A which is 440Hz as root note, then other waves would play multiples of that note: e.g 880Hz, an octave higher). This results in a more complex and richer sound. The best example of additive synthesis is the popular Hammond organ. We can see a virtual emulation as vst in figure 2.5. 16 FIGURE 2.5: Hammond vst 2.3.6 GRANULAR SYNTHESIS Granular synthesis is very similar to sampled synthesis. We start with a lot of small samples, called grains, that all together make a specific sound. We can control the grain size and other features in order to reshape the sound. Bigger or smaller steps between grains give the sound a new dimension that offers a lot of possibilities. The mangle, shown in figure 2.6, is a great example of granular synthesizer. 17 FIGURE 2.6: The mangle 2.3.7 OTHER TYPES OF SYNTHESIS We have a lot of options when it comes to create new sounds, and the way we can create them also create new types of synthesis. We have already depicted the most popular approaches to create sounds, but there’s definitely plenty of them we have kept out of the list but are still interesting such as physical modeling synthesis, spectral synthesis… Any new way of creating sounds can create a new category of synthesis so the possibilities are far beyond countable. 18 2.4 About DAWs and MIDI 2.4.1 DAWS In the previous chapter we briefly mentioned what a DAW and a plugin were, but we believe it is necessary to delve a little deeper into the history of DAWs in order to understand why we wanted to create a plugin for this type of software. [7] DAWs started to be born around the 80's, just when more powerful computers started to emerge, they implied, in the long run, a change of paradigm, as less people were required in the recording studios to work. This is due to the fact that less physical space was needed to work, the recording processes were more powerful, precise and flexible, and above all, a very important factor was being able to have automatic recall, that is, you could save a production/mix project and reopen it at the exact moment you left it, something that was impossible before the 80s, since an analogue system was used for this type of projects and you had to write down and take pictures of how everything was in order to set everything back to the way it was, and that took a long time. These were the first noticeable changes in DAWs, but they have continued to evolve until today, and have numerous improvements, such as being able to work in different places at the same time, share our projects on the internet, take them with us on a USB or collaborate simultaneously with other professionals thanks to the "cloud" and some DAWs are even compatible with smartphones. 19 FIGURE 2.7: Electronic music recording studio in the 1950s FIGURE 2.8: Today's electronic music recording studio 20 2.4.2 MIDI Now that we are a little more in context about what DAWs are, it's time to ask the question of how they are able to create sound. The answer can be found in the word MIDI. [8] MIDI is the acronym for "Musical Instrument Digital Interface". In other words, it is a standard that allows the exchange of musical information between synthesizers and computers. [9] When you use a MIDI instrument, every time you press a key, a MIDI note (sometimes called a MIDI event) is created. Each MIDI event carries with it the instructions that determine: ● The activation and deactivation of the key: when the key is pressed and when it is released. ● Velocity: how fast and how hard the key is pressed. ● Aftertouch: how hard the key is pressed and held. ● Tempo (or BPM): comes from the acronym "Beat per Minute, but we can say that it is the number of quarter notes that are played in one minute (musical figures). ● Panning: Broadly speaking, this is how much sound is heard on the right or left side. ● Modulations: Being able to change the pitch of the sound MIDI is just data, a set of instructions that machines use to talk to each other and that are transmitted over MIDI channels. Most MIDI instruments are capable of transmitting MIDI data on 16 channels simultaneously. That may not sound like much, but having only 16 channels is a good creative limitation. And they should be more than enough. 21 2.4.3 MIDI IN DAWS We've talked about DAWs and MIDI, but now it's time to look at how these two concepts are related. It may sound complex, but in reality it's as simple as most (if not all) DAWs can create and manipulate tracks using MIDI. The biggest advantage of this simple and inexpensive duo is that you can assign parameters in your DAW, and they often have a piano roll that allows you to edit sequences and compose with the help of the controller to play every part of your track. In addition, many MIDI controllers have knobs, pads and faders that can also be assigned through your DAW. Just as a final detail, it is not necessary to connect a MIDI controller to the computer where we have the DAW, since the piano roll itself allows us to create and manipulate MIDI events, although it is not as simple as pressing a key on our instrument. FIGURE 2.9: DAW and MIDI conection 22 FIGURE 2.10: A piano roll in a MIDI clip editor (Reaper). CHAPTER 3 – SYNTHESIZER MANUAL 3.1 Overall features 3.1.1 INSTALLATION For this memory we will guide you through the basic steps necessary to be able to use our project, and we will use the DAW REAPER[3] as a reference. The first step is to download and install a DAW to be able to use the VST version of the plugin. Next, we download the plugin [10] and place the file with the VST extension in a directory that we will use to place all our plugins, an example could be C:\Program Files\Common Files\VST. 23 If you want to use the standalone version, just run the plugin ending in .exe. 3.1.2 CONFIGURATION Once we have the DAW installed and open, we will look for an Options tab, then Preferences. What we want, is to find some options related to MIDI Devices. Figure 3.1: Reaper Preferences menu 24 In this section we have to activate our MIDI controller that is connected to the computer. Now to use our plugin, we simply have to insert or create a MIDI audio track, and add it. FIGURE 3.2: How to select Plugin in Reaper 3.1.3 BASIC USAGE The first thing we have to do is to create some MIDI signals as shown in figure 1.1 To do this, we just have to double click on the MIDI track created and something similar will open up. We simply have to add the signals to our liking (pitch and length) with the help of the mouse. Once we have the MIDI signals, we just have to open the visual part of our plugin, and it should look like in figure 3.3. 25 And finally, we just have to edit the parameters to taste and it will be applied immediately to our track. FIGURE 3.3: Visual plugin 3.2 ADSR ADSR stands for Atack, Decay, Sustain, Release respectively. The attack is used to mark the time it takes to reach the maximum output from the beginning of the sound. The decay is to set the time it takes for the sound to descend to the level of another parameter, the sustain, from the maximum. The sustain is the level at which the sound will remain constant. Finally, the release is the time it takes to get from the sustain level to the zero level of the sound. 26 3.2.1 ADSR KNOBS According to the 4 basic parameters of an ADSR, in order to manage it easily, we have chosen to create 4 circular sliders, one for each parameter, as shown in figure 3.4. ● Slider A corresponds to the Attack, from left to right, it can take the values from 0.00f to 10.00f having 0.001f as default value. ● Slider D corresponds to Decay, from left to right, it can take values from 0.00f to 1.00f with a default value of 0.10f. ● The S slider corresponds to the Sustain slider, from left to right, it can take values from 0.00f to 1.00f with a default value of 0.01f. ● The R slider corresponds to the Release slider, from left to right, it can take values from 0.00f to 20.00f with a default value of 0.4f. 3.2.2 ADSR VISUALIZER As we have been saying from the beginning, one of our goals is to make our plugin easy to use and understand for everyone. Therefore, apart from the sliders, we have opted for a graphical representation of these parameters, which change in real time according to the 4 sliders. In this way, every time (for example) the Decay is modified, the graph changes instantly. This can be seen in figure 3.4. 27 FIGURE 3.4: ADSR 3.3 Morph The morph feature might be the signature sound of our synthesizer. Figure 3.5 shows the display of the functionality. FIGURE 3.5: Morph 28 The main purpose of this feature is to blend different waveforms and output the results. If we take a look at the bigger rotary knob right under “MORPH”, we will see that when the knob is turned all the way to the left it doesn’t change anything. That is because it is the starting point at where the knob is bypassed because it has no ON/OFF switch. After that, the range is divided into 4 sections of equal length between 0 and 1( 0.01 - 0.25 | 0.25 - 0.5 and so on). Each one of these sections takes oscillators 1 and 2 waveforms and blends it with the following waveform in a circular arrangement. If our oscillator1 waveform is a sine wave, then the range of 0.01 to 0.25 will blend this signal with the next waveform and will apply a blend proportional to the knob position, being 0.01 the closest to a regular sine wave and 0.25 the closest to the next signal. Given that the synthesizer has 5 different waveforms implemented, the Morph functionality will be able to blend all the different waveforms possible (oscillators 1 and 2 take the original waveform and Morph uses the other 4 signals). In order to get a richer sound, the synthesizer has a built-in option to control some of the Morph functionalities. This is the Randomness rate feature. It lets the user randomize the Morph position in order to get a different mixture of the waveforms over the time. The user just have to click on the RND button to activate this function. After this, for some period of time the synthesizer will choose a random value for the Morph knob and will apply this to the sound. If we increase the Randomness Rate knob, this period of time will be shorter and shorter, making the synthesizer choose random Morph values at higher frequencies. The synthesizer applies all changes to both oscillators at the same time. The only case it doesn’t apply the effect is when mute is selected in the oscillator. In that case, the output signal of that oscillator is going to be 0 always. This means that muted oscillators won’t get any different results by applying the morph effect, but non muted oscillators will work the same. 29 3.4 DSP modules DSP stands for digital signal processor, usually referring to audio signals. In other words, it consists of performing mathematical operations with these audio signals, since they are digitised and converted into numbers. The result is a number that expresses a different audio signal. 3.4.1 DSP DELAY The delay is a sound effect that consists of delaying a sound signal. This signal is processed and then mixed with the original signal. One of the possible results after doing this is to get what we call an echo. You can have several parameters to create this sound echo, we will use three: ● Delay time: This is the time it takes for the echo to be produced. ● Wet: Used to indicate the amount of signal to be mixed between the original signal and the delayed signal. ● Feedback: Represents the number of times the signal is repeated. The delay section can be summarised in three sliders that control the above parameters and an OFF/ON button, as shown in figure 3.6. ● The Delay Time slider moves from bottom to top, it can take values from 0.0f to 3.0f respectively, having by default the value 2.0f. 30 ● The Wet slider moves from bottom to top, it can take values from 0.0f to 1.0f respectively, defaulting to 0.8f. ● Feedback slider moves from bottom to top, it can take values from 0.0f to 1.0f respectively, defaulting to 0.5f. And finally there is an OFF/ON button at the top, which indicates whether we turn the delay effect on or off. If it is not pressed, no matter the value of the parameters, the effect will not be working. FIGURE 3.6: Delay 3.4.2 DSP REVERB The reverb is a sound effect that is the result of the end of a sound, after it has interacted with the surrounding surfaces. In other words, a flute would not sound the same in an auditorium as it does in your own room, due to the distance between the walls. Reverb is about recreating these possible scenarios. To do this we will use 6 parameters: 31 ● RoomSize: Used to indicate the dimensions of the room in which we want our sound to be reproduced. ● Damping: Used to make the reverb sound as real as possible, since this parameter is equivalent to the acoustic absorption of the materials inside a room. ● Wet: Represents the amount of signal to which the reverb is applied. ● Dry: Represents the amount of signal to which reverb is not applied. ● Width: Used for expanding or collapsing the stereo image. ● FreezeMode: Used for the reverb to continue playing and never decay. Each of these parameters, as in the case of the delay and as can be seen in figure 3.7, will be represented with sliders to modify their values: ● The RoomSize slider moves from left to right, it can take values from 0.0f to 1.0f respectively, with the default value being 0.5f. ● The Damping moves from left to right, it can take values from 0.0f to 1.0f respectively, with the default value 0.5f. ● Wet moves from left to right, it can take values from 0.0f to 1.0f respectively, defaulting to 0.33f. 32 ● Dry moves from left to right, can take values from 0.0f to 1.0f respectively, defaulting to 0.4f. ● Width moves from left to right, it can take values from 0.0f to 1.0f respectively, defaulting to 1.0f. ● FreezeMode moves from left to right, can take values from 0.0f to 1.0f respectively, defaulting to 0.0f. And finally we have an OFF/ON button, which indicates whether or not to turn the reverb effect on or off. If it is not pressed, no matter the value of the parameters, the effect will not be working. FIGURE 3.7: Reverb 33 3.4.3 DSP FILTER The filter section is minimalistic and very straightforward. As we can see in figure 3.8 this section contains two rotary knobs and a drop down menu that lets you choose what kind of filter you want to apply to the audio chain. FIGURE 3.8: Filter The knob at the left displays a number in the range of 20 – 20.000. This range is not casual given that this is the human hearing range in Hertz. The lowest sound we are able to hear oscillates at a frequency of 20 Hertz and the highest one oscillates 20.000 times per second (it deeply depends on many factors such as age, internal structure of the ear…). The knob controls the cutoff frequency of the filter and it sets the frequency where the filter starts to work on the audio signal. Depending on the type of filter selected (Band-pass, Low-pass…) the audio processing will be applied on different ranges of the spectrum. For example, if you choose a Low-pass filter and a cutoff frequency of 400Hz, it will mitigate frequencies starting at 400Hz and above with a strength of 12 dB per octave, given that the DSP module of the filter in Juce is a first order filter. 34 The knob at the right displays the Q factor of the filter. This feature slightly changes how the filter is applied at the cutoff frequency. When you choose a value higher than one, the frequencies near the cutoff frequency will get a small boost, depending on the Q value chosen. The higher the Q value the higher the boost. As mentioned previously, this feature only changes a narrow band near the cutoff frequency, letting the filter work as usual on the rest of the spectrum. The functionality varies depending on the filter type. If you choose a low-pass or high-pass filter, it will work as described earlier. If you choose a band-pass or a notch filter, the Q factor will operate on the breadth of the band we are filtering. Smaller Q values will filter a narrower section of the spectrum while working with notch filters and the other way around. The same applies to the band-pass filter, it will let a narrower band of frequencies pass through the filter while using smaller Q values and the other way around too. Finally, the drop-down menu will let you choose between types of filters to be applied. We’ve already seen some of their utilities while looking at the knobs functionalities. It’s simple and self explanatory just by reading their names, but our options are: Low-pass, High-pass, Band-pass, Notch. Depending on which one we choose we’ll filter some of the frequencies from our audio chain. The Low-pass filter will let low frequencies pass through and will attenuate the higher frequencies. The High-pass filter works exactly opposite to the Low-pass filter. The Band-pass filter takes a band of frequencies from the spectrum and lets them through while it filters frequencies above and below that range. The notch filter is the opposite to the Band-pass filter. It attenuates frequencies in a certain range and lets higher and lower frequencies pass through. 35 3.5 Preset Manager As we are able to see in figure 3.9, the preset manager section is fairly simple and user friendly. You can manage custom presets by tweaking any synthesizer feature and saving it for later. FIGURE 3.9: Preset manager In order to load a preset you just have to click on the drop-down menu and choose one of the presets previously stored (this is an important step given that you need to have already some presets in order to load them, the synthesizer doesn’t come with default presets). This will automatically load the preset. You have to be careful because this will overwrite the current settings on your synthesizer, so if you want to keep these settings you will have to save your current state. You can achieve this by clicking on the save button on the right side of the drop-down menu. This will open a dialog where you are asked to type a name for your preset. You can actually have different presets with the same name although we don’t recommend this practice. You also have the option to delete a preset. In order to erase one you just have to select first the preset you want to delete, and then click on delete just underneath the save button. There is no prompt 36 dialog to make sure you clicked it on purpose so we recommend being extremely careful when using this feature, once you have deleted a patch there is no way to retrieve those settings. CHAPTER 4 - IMPLEMENTATION 4.1 Technologies We have implemented the synthesizer using JUCE as the main framework. It has a lot of utilities, functionalities and libraries to develop fully operational and professional audio software. Given that we were aiming to create a synthesizer, which is a very specific, complex and broad task, this was our best option. JUCE has already some built-in classes that lets you focus on the features of your synth instead of building it from scratch. Otherwise we would have had to create an audio framework which would have probably taken all of our time. Using the Synthesizer class, the PluginProcessor class and the PluginEditor class made a huge impact on time management during the process of building the synthesizer. We have also used the ProJucer tool, which lets you create and manage general settings of your audio application without too much trouble. This tool is the bridge between JUCE technology and our IDE’s. It prepares the environment and the classes you need to implement in a very user friendly way. Lastly we have used Microsoft Visual Studio as our main IDE. By debugging the code we were able to test the application in standalone mode. To test the VST version we just exported the project and tried it as a REAPER plugin, which gave us awesome results. 37 4.2 Audio chain 4.2.1 GENERATING AUDIO Generating a sine wave might be a complex task at first sight but once we know the basics is very straightforward. Digital audio, as opposed to real audio waves, has to be represented as a discrete amount of audio chunks in order to be perceived the same way we perceive actual sound. To fool our minds into thinking that digital audio has the same nature as real audio has, the amount of chunks (this will be called samples later on) taken from real audio needs to be properly spaced. In order to transform actual sound into digital audio we’ll need to capture it first. The way we capture audio is by measuring the state of the wavelength in a particular moment. Let’s say we’re trying to capture a pure tone (also known as sine wave) oscillating at a rate of 440Hz. This oscillation changes the pressure of the air between two given values 440 times per second. To properly capture the sound, we need to take “pictures” of that audio wave many times to see the way it oscillates between these two values. The standard is 44.100 samples per second. This means we are measuring air pressure (taking these “pictures”) 44.100 times per second to have a clear view of what’s happening with while playing this pure tone. We can repeat the process the other way around and send these “pictures” (from now on we’ll call them samples) to an audio system in order to make them play the same sound we captured. This is the basis of digital audio. In a synthesizer, audio is commonly generated digitally (depending on the type of synthesis as we’ve already seen in chapter 2). We don’t need to previously record analogue (real) audio to play any sound. In order to generate a sine wave, for example, we just need to know how to arrange the samples over the time to successfully emulate how an actual sine wave would sound. This samples will be sorted in a buffer. This buffer is where we load our samples and later on will be sent to the audio system to be played. The oscillator is the module in charge of generating this sound. By taking a simple equation over a variable over the time, it can play any type of waveform and send the values generated as samples to the buffer. 38 Now we have to be able to know which note we want to play at a certain time. We have to know that making waves oscillate at different rates is what gives them different notes. This is where midi comes into play. Midi is a signal that we send to the oscillator, and this signal contains all the information on how we want the oscillator to generate the sound. There’s a direct transformation that maps midi information to frequency. For example, when we play A4 on a piano that sends MIDI to a computer, the midi will let the oscillator know that we want to generate a 440Hz signal. We apply the same method to every note, and we can even send information to the synthesizer via midi about how hard we pressed the key and several other functionalities of real instruments. These are basic concepts we need to know that are happening underneath the synthesizer in order to fully understand how it operates. This will ease the process of understanding the audio chain and why we took decisions that we’ll talk about in the next section. 4.2.2 ABOUT AUDIO CHAIN The audio chain is one of the most important things to take into consideration when making any kind of audio processing device. The route that the audio takes from the main inputs to the outputs of the processor will make a huge impact on the final results. In order to visualize the importance of this let’s take a look at this quick example: Let’s suppose that we want to concatenate an equalizer and a reverb effect on a guitar solo. Now we apply the reverb effect, which will make some of the guitar frequencies “bounce” and feedback into the audio chain again, creating the characteristic reverb sound. If we apply the equalizer right after the reverb, we will be attenuating (in the case we use the equalizer to attenuate) the guitar sound and the reverb sound. Otherwise, if we first apply the equalizer and later on the reverb, the reverb won’t get the same frequencies that used in the first case to create that space, given that the original guitar frequencies don’t get past the equalizer. The variety of results we get by changing the order of the processors are virtually infinite. In our case, the diagram on figure 4.1 shows the audio chain of our synthesizer. 39 FIGURE 4.1: Audio chain We have chosen this implementation given that it is very logical. First we process the oscillators. This is a must because previous to this step we don’t have any audio to process so we have to generate it through the oscillators. Right after that we manage the gain through the gain slider. This will set the overall volume of the synthesizer in a range of 0 - 1. We can also see this as a percentage of the total volume of the synth, being 0 a 0% of the total output volume, which won’t let any audio pass through this dsp processor, or 1, which will output a 100% of the volume that goes into the processor. 40 After the overall volume we pass the signal through the ADSR dsp. This will shape the volume over the time of each one of the notes that the synthesizer generates. Everytime a note is pressed, the ADSR processes the volume envelope for that note depending on the ADSR values for attack, decay, sustain and release. After that the signal goes through the different dsp’s in the following order: 1. Reverb 2. Delay 3. Filter This audio chain was chosen over other permutations for multiple reasons. First of all, we decided that the filter had to be the last dsp to be applied to the audio chain. It doesn’t really matter (at least in a significant way) what kind of effects we put previous to the filter. We wanted the filter to process all the frequencies and upper harmonics that the previous dsp’s could generate, which otherwise would be missing just by changing the order and letting other dsp’s modify the filter’s output. Later on we decided that it was more important and would generate more pleasing sounds to have the reverb already applied on every reflected signal of the delay. This was actually a very hard decision given that the difference is very subtle, but we got better results at a subjective level by applying reverb in the first place. As future work for this section (which will be discussed later in chapter 4) we came to the conclusion that we can improve and extend the variety of sounds the synthesizer can provide by adding more dsp’s modules, and even find a way to let the user choose the way the signal routes through the different processors. 4.3 Oscillators and Morph The way the oscillators and morph work together is slightly complex. As we can see in the interface, we have 2 oscillators, 1 mix slider and 2 morph sliders. First of all, everytime we update the oscillators we make several operations to get the final wave value when using the initialise() function [11]. In every update we need to check the morph slider 41 state in order to see if there’s going to be a mixture of waveforms. As we’ve seen in Chapter 3 section 3.3, the morph feature blends the selected waveform with all the other waveforms depending on the slider position. This actually applies to both oscillators in the same way, following the scheme on figure 4.2: FIGURE 4.2: morph diagram To make this possible we’ll need 4 floating point variables. The first 2 variables will contain the values of the oscillators 1 and 2 respectively, and the other 2 variables will contain the morph values for oscillators 1 and 2. We also precalculate all the waveforms so we just have to make each operation once as we see in figure 4.3: 42 FIGURE 4.3: Waveforms After that, we assign the selected waveform from the combobox to variables wave1 and wave2 and calculate what are the auxWave1 and auxWave2 waveforms depending on the morph position. Given that we have 5 different waveforms, we have to make a decision excluding the current waveform selected (otherwise we could not mix anything) in a circular way. We came up with this quick algorithm to calculate both waveforms: FIGURE 4.4: code from morphChoice1 Once we know what are the morph waveforms we have to mix there’s 2 steps left: ● Apply morph value We already have calculated the values of the morph intensity of each one of the waves (morph intensity and its inverse). We just have to multiply the variable wave1 by morphIntensity and add the auxWave1 multiplied by morphIntensityInverse as shown in figure 4.5: 43 FIGURE 4.5: morph ● Apply mix value Then we multiply the result by the mix value. If we did this step the other way around, we might hear leaks of the variable auxWave1 even though the mix value was 0. For each one of the oscillators we return the values calculated. 4.3.1 RANDOM RATE MANAGEMENT We manipulate the randomness variables outside the oscillators. If RND is selected, everytime we update the oscillators we go through an algorithm in charge of creating movement in the waveforms. For that, we created a global variable called X that increases by 1 everytime we go through this process. Once this variable is bigger than the inverse of the randomRate variable (this sets the pace and quickness of the movement) we obtain a random value of the morph feature (in the range of 0-100) and reset the variable X to 0 in order to restart the process again. What we get by doing this is to randomly move the morph value at a certain rate given by the slider Randomness Rate as we see in figure 4.6. 44 FIGURE 4.6: Random rate This automatically updates the variables morphIntensityValue and morphIntensityInverse that are responsible for morph changes in the waveforms. By updating those variables we don’t have to make any changes to the main algorithm and we can add this kind of movement in a modular way just by activating this feature in the interface. 4.4 ADSR visualizer For the ADSR visualizer we’re using the built-in graphics tool [12]. This tool is capable of drawing lines, dots, and all kinds of 2D shapes. We decided that the optimal way of updating the ADSR visualizer was to create a callback function that invokes the function repaint() everytime one of the slider values changed. This might seem a waste of resources but we checked the memory usage and it remains under reasonable spendings. The repaint function is the only way to update a drawing on the interface and replace it with a new drawing, creating the effect of movement everytime it updates. We could have used the animation module of JUCE but this generates a lot of compatibility issues between an audio plugin and an animated component. 45 To figure out what we had to represent in the visualizer we took inspiration from other synthesizers like Serum, figure 4.7. FIGURE 4.7: Serum ADSR visualizer This figure shows 4 lines. This might seem counterintuitive given that we have to visually represent 4 parameters, but we can apply the similarity between natural numbers and gaps between them. If you count up to number 4, you’ll find that there’s 3 gaps between those numbers. Well, in our case we can see the ADSR parameters as nodes, being 1-Attack, 2-Decay, 3-Sustain, 4-Release and the gaps between these parameters as the lines we want to represent. The main idea behind the algorithm is to first calculate 4 positions, which will be the obtained taking into account the current values of the ADSR, an imaginary rectangle with the limits of the ADSR visualizer and the separation between each dot. Some aesthetic and design choices were made. For example, the width between each dot is different depending on the ADSR values, giving more space to higher values in proportionally to each other. This way is much simpler to visualize the current state of the ADSR values just by taking a quick look at the drawing. After getting the position and creating these point objects (not drawing them), we proceed to create the line objects which will carry the information about the path that follows those points. At this point we could stop and directly draw the lines. This would make a functional visualizer but we’ve taken it to the next level in order to be prepared for future versions of the synthesizer. 46 We came up with the idea of showing a small animation to make it more interesting. For that, we thought we could draw the lines dot by dot, from left to right. This is requires more computations but we managed to make it fairly simple. We just iterate over different points of the line with a for loop. We just need the following functions[13]: ● getPointAlongLine(float) ● getLength() Now we have every dot along the line with the convenient accuracy and spacing. We just have to draw small ellipses (this way we can control the stroke width) on those points and we are ready to go. For the animation we would need the AnimatedAppComponent class [14], but we’ve encountered many problems while trying to combine this kind of component into an audio application, so we’ve left this section unimplemented for now, although the visualizer works perfectly fine. 4.5 DSP modules [15] DSP modules implementation is very straightforward. JUCE already developed some premade classes that we can use for that. Instead of writing the signal processing from scratch, JUCE let us set these classes in our project and call them everytime we need to apply some effect. All the effects we implemented work the same way. First, when we are going to process the next audio block, we update all the information of each one of the DSPs states. Once we have gathered all the necessary information, we process each effect following the audio chain (Chapter 4 - 4.2) using the struct ProcessContextReplacing [16], which let us completely process the input signal and output the same signal already processed. Using this method we avoid creating duplicates of the audio signal and apply the effect at its maximum. We have to take into consideration that the dsp modules can control the amount of wet and dry signal by themselves. 47 ● Reverb Pass parameters to reverb dsp using updateReverb() → Figure 4.8 FIGURE 4.8: Reverb params Apply reverb → Figure 4.9 FIGURE 4.9: Reverb processing 48 ● Delay Pass parameters to delay dsp using updateDelay() → Figure 4.10 FIGURE 4.10: Delay parameters We can see that there are 2 different channels (left and right) with the same DelayTime. On future updates of the synthesizer we’ll implement a feature to control each channel independently. This way we will be able to achieve a “ping pong” delay style. 49 Apply delay→ Figure 4.11 FIGURE 4.11: Delay processing ● Filter Pass parameters to filter dsp using updateFilter() → Figure 4.12 FIGURE 4.12: Filter states In this case the parameters only modify the type of filter we are applying. They all use the same parameters so there is no conflict between one another. For further versions we would need to collect more parameters in order to create different filters such as shelf type filters (we would need to collect the gain amount). 50 Apply filter→ Figure 4.13 FIGURE 4.13: Filter processing 4.6 Preset manager The implementation of the preset manager was made following John Flynn’s work on his project TestParameters02 [17]. He has several functions that provide a lot of utilities while doing this task. We had to refactor the code in order to make it work with our version given that he designed it to work on different components and we only have one component. The main idea he follows for saving presets of the synthesizer is to save the current state of the parameters of the audio processor to a XML file [18] so you can retrieve them later. For that he uses the next list of functions that we’ll briefly explain: ● saveStateToXml Saves the current state of the audio processor parameters to an XML element. ● loadStateFromXml Loads the parameters of an XML element into the audio processor. ● savePreset Saves the current preset assigning an ID and name to the preset. ● loadPreset Loads a preset using its ID. ● deletePreset Deletes a preset from the list using its ID. ● getPresetNames 51 Returns a list of names of the presets that the XML element currently has. ● getNumPresets Returns the number of presets stored in the XML element. ● getCurrentPresetId Returns the current preset ID, which is a global variable to uniquely identify each preset. ● populateComboBox Adds the list of preset names to the combobox element. ● getNextAvailablePresetID Returns the next preset ID available in a string format. ● comboBoxChanged Updates the current selected preset in the combobox element. ● refreshPresetBox Updates the list of preset names in the combobox element. ● ifPresetActiveShowInBox Updates the current active preset in the combobox element. ● deletePresetAndRefresh Deletes a preset and refresh the combobox to show the current presets available. ● savePresetAlertWindow Displays the alert window that lets you enter the name of the preset and accept or cancel this action. 52 CHAPTER 5 - CONCLUSIONS AND FUTURE WORK 5.1 Conclusions Our synthesizer is capable of creating and playing MIDI signals, either from a DAW or from a computer, although in the latter it is necessary to have an instrument or tool connected that can produce MIDI signals. Our project has a great variety of functionalities, as we have been explaining, all of them allow it to be used from a simple way, to a more complex way. Its main functionality is ultimately to be able to create sound using MIDI signals, simple features such as effects like delay, being able to control parameters like ADSR or managing the volume have been included. But there are also more complex features such as Morph and Randomness Rate. We must recognize that JUCE (both its forums and the Projucer program) has been a great help to create a basic structure to start the development of our plugin. It has a wide variety of libraries that have been relatively useful for us. It is also worth mentioning that without JUCE we would not have been able to make the two versions of the plugin without complications, since the projucer has been in charge of compiling and creating the two versions using the same source files. The plugin has been tested and tested in both VST3 and standalone versions, but it is only available for Windows. 5.2 Future work The plugin can be improved in many ways, you could say that the things that can be added are almost infinite. For example more classic effects like a phaser or exciter, or even a set of default presets that can recreate characteristic sounds. 53 You could add things like an LFO, although needless to say, we've tried that, it would be something that would also add a lot to our plugin. Another improvement that could be included, would be to add more oscillators or a sampler to be able to mix more sounds and therefore give more free rein to the imagination. Following in the dynamic of improving our project we could add a second sale in the graphical representation, to separate some features, although this would be more focused on the visual part than the synthesizer itself. 54 BIBLIOGRAFÍA [1] https://dle.rae.es/sintetizador [2] https://www.producersphere.com/daw-definition/ [3] https://www.reaper.fm/download.php [4] https://www.thomann.de/blog/es/historia-de-los-sintetizadores/ [5] https://thebassvalley.com/breve-historia-de-los-sintetizadores/ [6]https://juanmasoundguy.wordpress.com/2019/09/24/que-es-un-daw-definiciones-y-a lgo-de-historia/ [7] https://en.wikipedia.org/wiki/Synthesizer [8] https://dictionary.university/MIDI [9]https://blog.landr.com/es/que-es-el-midi-la-guia-del-principiante-para-la-herramient a-musical-mas-poderosa/ [10]https://drive.google.com/drive/folders/1Y7_CdSvugSt4Lcaa4Rb-VvHF5U0q2Tmu?us p=sharing [11] https://docs.juce.com/master/classdsp_1_1Oscillator.html [12] https://docs.juce.com/master/tutorial_graphics_class.html [13] https://docs.juce.com/master/classLine.html [14] https://docs.juce.com/master/classAnimatedAppComponent.html [15] https://docs.juce.com/master/tutorial_dsp_introduction.html [16] https://docs.juce.com/master/structdsp_1_1ProcessContextReplacing.html#details [17] https://github.com/johnflynnjohnflynn/TestParameters02 [18] https://docs.juce.com/master/classXmlElement.html 55 https://dle.rae.es/sintetizador https://www.producersphere.com/daw-definition/ https://www.reaper.fm/download.php https://www.thomann.de/blog/es/historia-de-los-sintetizadores/ https://thebassvalley.com/breve-historia-de-los-sintetizadores/ https://juanmasoundguy.wordpress.com/2019/09/24/que-es-un-daw-definiciones-y-algo-de-historia/ https://juanmasoundguy.wordpress.com/2019/09/24/que-es-un-daw-definiciones-y-algo-de-historia/ https://en.wikipedia.org/wiki/Synthesizer https://dictionary.university/MIDI https://blog.landr.com/es/que-es-el-midi-la-guia-del-principiante-para-la-herramienta-musical-mas-poderosa/ https://blog.landr.com/es/que-es-el-midi-la-guia-del-principiante-para-la-herramienta-musical-mas-poderosa/ https://docs.juce.com/master/classdsp_1_1Oscillator.html https://docs.juce.com/master/tutorial_graphics_class.html https://docs.juce.com/master/classLine.html https://docs.juce.com/master/classAnimatedAppComponent.html https://docs.juce.com/master/tutorial_dsp_introduction.html https://docs.juce.com/master/structdsp_1_1ProcessContextReplacing.html#details https://github.com/johnflynnjohnflynn/TestParameters02 https://docs.juce.com/master/classXmlElement.html