# Working with Images

## Getting the sprawl access point image

Download the operating system image for the sprawl access points! According to its postfix .xz the image is compressed with the XZ compression algorithm. Before writing the image to the sd card it has to be decompressed.

On Ubuntu/Debian you can install xz-utils and use unxz:

$sudo apt-get install xz-utils unxz sprawl_pi_image_20200628_shrinked.img.xz  On MacOS try the unarchiver. On Windows try the usual way to decompress files or download xz-utils. ## Writing images on sd card ### MacOS ➜ ~ diskutil list /dev/disk0 (internal, physical): #: TYPE NAME SIZE IDENTIFIER 0: GUID_partition_scheme *1.0 TB disk0 1: EFI EFI 209.7 MB disk0s1 2: Apple_APFS Container disk1 1000.0 GB disk0s2 /dev/disk1 (synthesized): #: TYPE NAME SIZE IDENTIFIER 0: APFS Container Scheme - +1000.0 GB disk1 Physical Store disk0s2 1: APFS Volume OWC Aura Pro SSD - Data 520.8 GB disk1s1 2: APFS Volume Preboot 82.6 MB disk1s2 3: APFS Volume Recovery 525.8 MB disk1s3 4: APFS Volume VM 2.1 GB disk1s4 5: APFS Volume OWC Aura Pro SSD 11.2 GB disk1s5 /dev/disk2 (internal, physical): #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *63.9 GB disk2 1: Windows_FAT_32 boot 268.4 MB disk2s1 2: Linux 63.6 GB disk2s2  disk2 seems to be the sd card with 64 GB. To access the raw device /dev/rdisk2 is used. To write to this device you have to be root (administrator). Unmount the device before using dd. diskutil unmountDisk /dev/disk2 sudo dd if=rpi.img of=/dev/rdisk2 bs=4M  ### Linux $ sudo dd if=rpi.img of=/dev/disk/by-id/
ata-PLDS_DVD-RW_DS8A8SH_S45N7592Z1ZKBE0758TK
ata-SAMSUNG_MZMPA016HMCD-000L1_S11BNEACC10413
ata-SAMSUNG_MZMPA016HMCD-000L1_S11BNEACC10413-part1
ata-SAMSUNG_MZMPA016HMCD-000L1_S11BNEACC10413-part2
ata-SAMSUNG_MZMPA016HMCD-000L1_S11BNEACC10413-part3
ata-SanDisk_SSD_PLUS_240GB_184302A00387
ata-SanDisk_SSD_PLUS_240GB_184302A00387-part1
ata-SanDisk_SSD_PLUS_240GB_184302A00387-part2
ata-SanDisk_SSD_PLUS_240GB_184302A00387-part3
ata-SanDisk_SSD_PLUS_240GB_184302A00387-part4
ata-SanDisk_SSD_PLUS_240GB_184302A00387-part5
mmc-SDC_0x000000e2
mmc-SDC_0x000000e2-part1
wwn-0x5001b448b9edd143
wwn-0x5001b448b9edd143-part1
wwn-0x5001b448b9edd143-part2
wwn-0x5001b448b9edd143-part3
wwn-0x5001b448b9edd143-part4
wwn-0x5001b448b9edd143-part5
$sudo dd if=rpi.img of=/dev/disk/by-id/mmc-SDC_0x000000e2 bs=4M status=progress  ### Windows On Windows the easiest way to write an image to a sd card is to use a dedicated application like Balena Etcher. # Envelopes: ADSR Envelopes are an essential part of control in electronic music and computer music. They are used to shape the characteristics of sound or other processes over time and are an integral part of synthesizers. Since they are that basic and versatile, they will be introduced in this early section. One of the most common envelopes, already featured in early synthesizers and in prominent examples as the MiniMoog, is the ADSR envelope (Hiyoshi, 1979). It is comprised of four segments: • Attack • Decay • Sustain • Release Attack time, decay time and release time can usually be controlled by the user via dials or sliders, whereas the sustain time depends on the duration a key is pressed and the sustain level may depend on the stroke velocity. Depending on the settings, the ADSR model can generate amplitude and timbral envelopes for slowly evolving sounds like strings or sounds with sharp attacks and release: Your browser does not support the HTML5 canvas tag Attack Time: Decay Time: Sustain Level: Sustain Time: Release Time: When used in synthesizers, this envelope can be used to control the overall level or the timbre - for example through the cutoff frequency of a filter or by means of partial amplitudes. ## References • Teruo Hiyoshi, Akira Nakada, Tsutomu Suzuki, Eiichiro Aoki, and Eiichi Yamaga. Envelope generator. December 18 1979. US Patent 4,178,826. [BibTeX▼] • # Working with Groups ## Creating Groups Groups - or group nodes - can be a very useful concept for keeping track of the signal flow. Without any further actions, all nodes are placed in the default Group 1. Additional groups can be arranged regarding the order of execution. A new group can be added from sclang as follows: ~g1 = Group.new();  ## Relative Group Positions As with nodes, further groups can be added in relation to existing groups. The following action makes sure that a new group will be placed after the previously defined group: ~g2 = Group.after(~g1);  ## Nested Groups Groups can contain other groups, allowing a hierarchical structure of nodes: ~g3 = Group.head(~g2);  ## More on Groups The group object allows many more actions. They are listed in the SC documentation on groups. After adding another group before the third one ~g4 = Group.before(~g3);  the server node structure looks as follows: The server does not know the groups by their variable names in sclang. Hence they are numerated. Node indices - or IDs - of groups can be assessed from the language: ~g1.nodeID; ~g2.nodeID; ~g3.nodeID; ~g4.nodeID;  ### Exercise Exercise Use groups to sort the nodes from the example in the section on Combining Nodes # FM Synthesis: Formula & Spectrum # Pulse Width Modulation # Organizing Processes with systemd systemd is a set of tools managing, among other things, the startup procedure on Linux systems. Within the Linux user and developer community, there is a debate whether systemd violates the Unix philosophy - however, it works well for starting all the software components we need when booting the server or the Access Points. System services can be started in dependence of other services, making it possible to launch a system in with many interrelations. They can be started and stopped during operation. Depending on the configuration, services can also be restarted automatically when crashing. ## Creating Services systemd services can be declared as user services or system services. They are defined in text files, which need to be located in one of the the following directories: /usr/lib/systemd/user /usr/lib/systemd/system  ### The JACK Service The JACK service needs to be started before all other audio applications, since they rely on a running JACK server. A file jack.service defines the complete service: [Unit] Description=Jack audio server After=sound.target local-fs.target [Install] WantedBy=multi-user.target [Service] Type=simple PrivateTmp=true Environment="JACK_NO_AUDIO_RESERVATION=1" ExecStart=/usr/bin/jackd -P 90 -a a -d dummy -p 128 LimitRTPRIO=95 LimitRTTIME=infinity LimitMEMLOCK=infinity User=studio  ## Managing Services Once the service files are in place, several simple commands are available for controlling them. They differ, depending on whether a user service or system service is controlled. The following examples refer to the JACK user service. Controlling system services requires root privileges and do not need the --user flag. ### Starting a Service systemctl --user start jack.service  ### Stopping a Service systemctl --user stop jack.service  ### Activating a Service Activating a service creates a symlink in ~/.config/systemd/user/multi-user.target.wants/jack.service, pointing to the original file /usr/lib/systemd/user/jack.service. Afterwards, the system is launched on every boot. systemctl --user enable jack.service  ### Deactivating a Service systemctl --user disable jack.service  ### Getting a Service's Status The following command prints a system's status: systemctl --user status jack.service  When the JACK sevice has been started sucessfully, the output looks as follows:  ● jack.service - Jack audio server Loaded: loaded (/usr/lib/systemd/user/jack.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2021-04-13 23:00:14 BST; 3s ago Main PID: 214518 (jackd) CGroup: /user.slice/user-1000.slice/user@1000.service/jack.service └─214518 /usr/bin/jackd -P 90 -a a -d dummy -p 256  # Using APIs with Python ## Python & APIs With the modules requests and json it is easy to get data from APIs with Python. Using the above introduced methods for sequencing, the following example requests a response from https://www.boredapi.com/: #!/usr/bin/env python3 import requests import json response = requests.get("https://www.boredapi.com/api/activity") data = response.json() print(json.dumps(data, sort_keys=True, indent=4)) # print(data["activity"])  # Combining Nodes in SuperCollider ## Creating and Connecting Nodes Audio buses can be used to connect synth nodes. In this example we will create two nodes - one for generating a sound and one for processing it. First thing is an audio bus: ~aBus = Bus.audio(s,1);  The ~osc node generates a sawtooth signal and the output is routed to the audio bus: ~osc = {arg out=1; Out.ar(out,Saw.ar())}.play; ~osc.set(\out,~aBus.index);  The second node is a simple filter. Its input is set to the index of the audio bus: ~lpf = {arg in=0; Out.ar(0, LPF.ar(In.ar(in),100))}.play; ~lpf.set(\in,~aBus.index);  Warning Although everything is connected, there is no sound at this point. SuperCollider can only process such chains if the nodes are arranged in the right order. The filter node can be moved after the oscillator node: ## Moving Nodes The moveAfter() function is a quick way for moving a node directly after a node specified as the argument. The target node can be either referred to by its node index or by the related name in sclang: ~lpf.moveAfter(~osc)  # Pure Data: Send-Receive & Throw-Catch ## Send & Receive ### Control Rate Send and receive objects allow a wireless connection of both control and audio signals. The objects are created with send and receive or short s and r for control rate signals and get one argument - a string labeling the connection. #### Local Sends Prepending a$0- to a send label turns it into a local connection. These are only valid inside a patch and its subpatches but not across different abstractions. The example send-receive-help.pd shows the difference between local and global sends when used in both cases. It relies on the additional abstraction send-receive.pd which needs to be in the same directory:

Send and receive of control signals with subpatch and abstraction.

The inside of both the subpatch and the abstraction are identical:

Inside of send-receive and the subpatch.

### Audio Rate

Audio send and receives follow the same rules as control ones. They are created with an additional ~, as usual for audio objects. The example send-receive-audio.pd shows the use of these buses:

Send and receive of audio signals with subpatch and abstraction.

## Throw & Catch

Throw and catch are bus extensions of the above introduced send-receive method, only for audio signals. Unlike with s~ and r~, it is possible to send multiple signals to one catch~. This allows a flexible audio routing and grouping without a lot of lines. The example throw-catch.pd throws four sine waves to a common bus for a minimal additive synthesis:

Using throw and catch to merge four signals.

# Sampling & Aliasing: Square Example

For the following example, a sawtooth with 20 partials is used without band limitation. Since the builtin Web Audio oscillator is band-limited, a simple additive synth is used in this case. At a pitch of about $2000 Hz$, the aliases become audible. For certain fundamental frequencies, all aliases will be located at actual multiples of the fundamental, resulting in a correct synthesis despite aliasing. In most cases, the mirrored partials are inharmonic and distort the signal and for higher fundamental frequencies the pitch is fully dissolved.

Pitch (Hz):

Output Gain:

Time Domain:

Frequency Domain:

## Anti-Aliasing Filters

In analog-to-digital conversion, simple anti-aliasing filters can be used to band-limit the input and discard signal components above the Nyquist frequency. In case of digital synthesis, however, this principle can not be applied. When generating a square wave signal with an infinite number of harmonics, aliasing happens instantaneously and can not be removed, afterwards.

## Band Limited Generators

In order to avoid the aliasing, band-limited signal generators are provided in most audio programming languages and environments.

Contents © Henrik von Coler 2021 - Contact