Author: transif
Date: 2010-07-30 21:02:43 +0000 (Fri, 30 Jul 2010)
New Revision: 169
Modified:
community/f13/pt-PT/Hardware.po
Log:
l10n: Updates to Portuguese (pt) translation
Transmitted-via: Transifex (translate.fedoraproject.org)
Modified: community/f13/pt-PT/Hardware.po
===================================================================
--- community/f13/pt-PT/Hardware.po 2010-07-27 16:40:20 UTC (rev 168)
+++ community/f13/pt-PT/Hardware.po 2010-07-30 21:02:43 UTC (rev 169)
@@ -1,3 +1,4 @@
+#
# AUTHOR <EMAIL@ADDRESS>, YEAR.
# Nuno Miranda <nunmiranda(a)gmail.com>, 2010.
msgid ""
@@ -4,21 +5,29 @@
msgstr ""
"Project-Id-Version: 0\n"
"POT-Creation-Date: 2010-05-13T23:18:04\n"
-"PO-Revision-Date: 2010-06-28 21:56+0100\n"
+"PO-Revision-Date: 2010-07-07 11:37+0100\n"
"Last-Translator: Nuno Miranda <nunmiranda(a)gmail.com>\n"
"Language-Team: trans-pt(a)lists.fedoraproject.org\n"
+"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: application/x-publican; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Language: pt\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Virtaal 0.5.2\n"
+"X-Generator: Virtaal 0.6.1\n"
#. Tag: title
#, no-c-format
msgid "Hardware And Communication"
msgstr "Hardware e comunicação"
+#. Tag: para
+#, no-c-format, fuzzy
+msgid "This chapter gives an overview of some of the hardware available for wireless LANs, the role they play, and further details about their operation."
+msgstr ""
+"Este capítulo apresenta uma visão geral de alguns hardwares disponíveis para "
+"LANs sem fios, o papel que desempenham, além de detalhes adicionais sobre o "
+"seu funcionamento."
+
#. Tag: title
#, no-c-format
msgid "Components of a Wireless LAN"
@@ -27,47 +36,85 @@
#. Tag: para
#, no-c-format
msgid "In order for successful communications to take place in a WLAN, certain hardware is needed. The hardware can be generally categorized as being a <emphasis>transmitter</emphasis>, <emphasis>antenna</emphasis>, a <emphasis>receiver</emphasis>, or a combination of these."
-msgstr "Para obter comunicações de sucesso ao posicionar uma WLAN, determinado hardware é necessário. O hardware pode ser categorizado genericamente como sendo <emphasis>Transmissor</emphasis>, <emphasis>antena</emphasis>, um <emphasis>receptor</emphasis>, ou uma combinação destes. "
+msgstr ""
+"Para obter comunicações de sucesso ao posicionar uma WLAN, determinado "
+"hardware é necessário. O hardware pode ser categorizado genericamente como "
+"sendo <emphasis>Transmissor</emphasis>, <emphasis>antena</emphasis>, um "
+"<emphasis>receptor</emphasis>, ou uma combinação destes. "
#. Tag: para
#, no-c-format, fuzzy
msgid "Transmitter - A transmitter, as an <emphasis>active</emphasis> device, initiates an electromagnetic signal, beginning the wireless communication process. Usually, a transmitter sends this signal to an antenna after the data has been received by the originating station (ie. computer)."
-msgstr "Transmissor - Um transmissor, como dispositivo <emphasis>activo</emphasis>, inicia um sinal electromagnético, iniciando desta forma o processo da comunicação sem fios. Normalmente, o transmissor emite o sinal para uma antena após os dados serem recebidos pela estação de origem (exemplo. computador)."
+msgstr ""
+"Transmissor - Um transmissor, como dispositivo <emphasis>activo</emphasis>, "
+"inicia um sinal electromagnético, iniciando desta forma o processo da "
+"comunicação sem fios. Normalmente, o transmissor emite o sinal para uma "
+"antena após os dados serem recebidos pela estação de origem (exemplo. "
+"computador)."
#. Tag: para
#, no-c-format, fuzzy
msgid "Antenna - An antenna acts as an intermediary device in a WLAN. Specifically, it can propagate a signal after it has been received from a transmitter as an AC signal and then <emphasis>passively</emphasis> creates the waveform for it to travel through the air. The actual shape and path that the electromagnetic waves take depends on the type of antenna, its intended purpose and its desired coverage area. An antenna also performs the reverse of this operation by receiving signals and passing them along to a receiver."
-msgstr "Antena - Uma antena actua como dispositivo intermidiário numa WLAN. Especificamente, consegue propagar o sinal depois de ter sido recebido por um transmissor como um sinal AC e então <emphasis>passivamente</emphasis> cria uma forma de onda que atravessa o ar. A forma e caminho actual que as ondas electromágneticas adquirem depende do tipo de antena, do propósito planeado e da área de cobertura pretendida. Uma antena também leva a cabo a operação inversa ao receber sinais e os enviar para o receptor."
+msgstr ""
+"Antena - Uma antena actua como dispositivo intermidiário numa WLAN. "
+"Especificamente, consegue propagar o sinal depois de ter sido recebido por "
+"um transmissor como um sinal AC e então <emphasis>passivamente</emphasis> "
+"cria uma forma de onda que atravessa o ar. A forma e caminho actual que as "
+"ondas electromágneticas adquirem depende do tipo de antena, do propósito "
+"planeado e da área de cobertura pretendida. Uma antena também leva a cabo a "
+"operação inversa ao receber sinais e os enviar para o receptor."
#. Tag: para
#, no-c-format, fuzzy
msgid "Receiver - A receiver completes the electromagnetic communications in a WLAN by taking a signal (usually from an antenna) and passing it to the computer in a way it can understand (such as binary 1s and 0s)."
-msgstr "O receptor - O receptor completa as comunicações electromagnéticas numa WLAN ao captar o sinal (usualmente duma antena) e o enviar para o computador numa forma que possa ser entendido (tal como código binário 1s e 0s)."
+msgstr ""
+"O receptor - O receptor completa as comunicações electromagnéticas numa WLAN "
+"ao captar o sinal (usualmente duma antena) e o enviar para o computador "
+"numa forma que possa ser entendido (tal como código binário 1s e 0s)."
#. Tag: title
-#, no-c-format,
+#, no-c-format,
msgid "Types of Cards"
msgstr "Tipos de placas"
#. Tag: para
#, no-c-format
msgid "Wireless client adapters allow desktop and mobile computers to join and communicate on a WLAN. Adapters are typically available in PCI, PCI Express, Mini-PCI, USB, ExpressCard, Cardbus and PCMCIA form. This chapter provides details and sample images of three of the most commonly used adapter types: USB, PCMCIA/Cardbus, and PCI."
-msgstr "Os adaptadores de redes sem fios permitem que os computadores fixos e os portáteis se possam ligar e comunicar numa WLAN. Os típicos adaptadores disponíveis são PCI, PCI Express, Mini-PCI, USB, ExpressCard, Cardbus and PCMCIA form. Este capítulo disponibiliza detalhes e exemplos de imagens dos três tipos de adaptadores mais comuns: USB, PCMCIA/Cardbus, and PCI."
+msgstr ""
+"Os adaptadores de redes sem fios permitem que os computadores fixos e os "
+"portáteis se possam ligar e comunicar numa WLAN. Os típicos adaptadores "
+"disponíveis são PCI, PCI Express, Mini-PCI, USB, ExpressCard, Cardbus and "
+"PCMCIA form. Este capítulo disponibiliza detalhes e exemplos de imagens dos "
+"três tipos de adaptadores mais comuns: USB, PCMCIA/Cardbus, and PCI."
#. Tag: para
#, no-c-format
msgid "USB - These adapters are particularly useful for mobile users, allowing quick access for any machine with a USB port. They can be quickly set up and transferred between machines. The antenna is built into an integrated unit and the adapters are approximately the same size as a USB flash memory adapter:"
-msgstr "USB - Este tipo de adaptadores são particularmente úteis para os utilizadores que possuem dispositivos móveis, permitindo o acesso rápido de qualquer máquina que possua uma porta USB. Podem ser configurados rapidamente e transferidos entre máquinas. A antena é construída dentro de uma unidade integrada e os adaptadores têm aproximadamente o mesmo tamanho que um adaptador de memória flash USB :"
+msgstr ""
+"USB - Este tipo de adaptadores são particularmente úteis para os "
+"utilizadores que possuem dispositivos móveis, permitindo o acesso rápido de "
+"qualquer máquina que possua uma porta USB. Podem ser configurados "
+"rapidamente e transferidos entre máquinas. A antena é construída dentro de "
+"uma unidade integrada e os adaptadores têm aproximadamente o mesmo tamanho "
+"que um adaptador de memória flash USB :"
#. Tag: para
#, no-c-format
msgid "PCMCIA/Cardbus - Designed for laptops, these adapters can have an integrated antenna; however, some models provide support for connecting an external antenna to modify signal requirements, or increase signal strength capabilities:"
-msgstr "PCMCIA/Cardbus - Desenhado para portáteis, estes adaptadores podem possuir uma antena integrada; contudo, alguns modelos disponibilizam suporte de como ligar uma antena externa para modificar os requisitos de sinal, ou aumentar a capacidade de força do sinal:"
+msgstr ""
+"PCMCIA/Cardbus - Desenhado para portáteis, estes adaptadores podem possuir "
+"uma antena integrada; contudo, alguns modelos disponibilizam suporte de como "
+"ligar uma antena externa para modificar os requisitos de sinal, ou aumentar "
+"a capacidade de força do sinal:"
#. Tag: para
#, no-c-format
msgid "PCI - These adapters are available for desktop machines with a standard PCI slot. They typically have an external antenna attached, and provide support for connecting antennas for specific signal requirements, or for increased signal strength:"
-msgstr "PCI - Estes adaptadores estão disponíveis para computadores de secretária que possuem slot standard PCI. Tipicamente têm uma antena externa incorporada, e disponibilizam suporte para ligar antenas com requirimentos de sinal específico, ou para aumentar a força do sinal:"
+msgstr ""
+"PCI - Estes adaptadores estão disponíveis para computadores de secretária "
+"que possuem slot standard PCI. Tipicamente têm uma antena externa "
+"incorporada, e disponibilizam suporte para ligar antenas com requirimentos "
+"de sinal específico, ou para aumentar a força do sinal:"
#. Tag: title
#, no-c-format
@@ -77,22 +124,41 @@
#. Tag: para
#, no-c-format, fuzzy
msgid "There are three main antenna categories available for wireless LANs: <emphasis>Omnidirectional</emphasis>, <emphasis>Semidirectional</emphasis> and <emphasis>Highly directional</emphasis>."
-msgstr "Existem três categorias principais de antenas disponíveis para redes LANs sem fios: <emphasis>Omnidireccionais</emphasis>, <emphasis>Semi-direccionais</emphasis> e <emphasis>Altamente direccionais</emphasis>."
+msgstr ""
+"Existem três categorias principais de antenas disponíveis para redes LANs "
+"sem fios: <emphasis>Omnidireccionais</emphasis>, <emphasis>Semi-"
+"direccionais</emphasis> e <emphasis>Altamente direccionais</emphasis>."
#. Tag: para
#, no-c-format
msgid "Omnidirectional - <emphasis>Omnidirectional antennas</emphasis> are designed to radiate a signal in all directions. Although it is impossible under the basic laws of physics for an antenna to perfectly radiate a signal in all directions at equal strength, an antenna of this type is an attempt to provide general coverage in all directions. This is the most common type found for client adapters and access points, as in these situations, good coverage in a general spherical area around the antenna is desirable."
-msgstr "Omnidireccional - <emphasis>Antenas omnidireccionais</emphasis> são designadas por propagar o sinal para todas as direcções. Embora seja impossível pelas leis básicas da física que uma antena propague um sinal perfeito em todas as direcções com a mesma força de sinal, uma antena deste tipo tenta disponibilizar uma cobertura geral em todas as direcções. Este método é o mais comum utilizado nos adaptadores e pontos de acesso, nestas situações, uma boa cobertura numa área esférica em redor da antena é desejável."
+msgstr ""
+"Omnidireccional - <emphasis>Antenas omnidireccionais</emphasis> são "
+"designadas por propagar o sinal para todas as direcções. Embora seja "
+"impossível pelas leis básicas da física que uma antena propague um sinal "
+"perfeito em todas as direcções com a mesma força de sinal, uma antena deste "
+"tipo tenta disponibilizar uma cobertura geral em todas as direcções. Este "
+"método é o mais comum utilizado nos adaptadores e pontos de acesso, nestas "
+"situações, uma boa cobertura numa área esférica em redor da antena é "
+"desejável."
#. Tag: para
#, no-c-format
msgid "Semidirectional - <emphasis>Semidirectional antennas</emphasis> are designed to provide specific, directed signal coverage over large areas. An example of a semidirectional antenna is a <emphasis>Yagi antenna</emphasis>."
-msgstr "Semi-direccional - <emphasis>Antenas semi-direccionais</emphasis> são designadas especificamente por disponibilizar, um sinal direccionado através de largas áreas. Um exemplo de uma antena semi-direccional é a <emphasis>Antena Yagi</emphasis>."
+msgstr ""
+"Semi-direccional - <emphasis>Antenas semi-direccionais</emphasis> são "
+"designadas especificamente por disponibilizar, um sinal direccionado através "
+"de largas áreas. Um exemplo de uma antena semi-direccional é a "
+"<emphasis>Antena Yagi</emphasis>."
#. Tag: para
#, no-c-format, fuzzy
msgid "Highly-directional - <emphasis>Highly directional</emphasis> antennas are used for point-to-point links; for example, between two buildings. They radiate a very narrow beam over a long distance, and are often used for dedicated links."
-msgstr "Altamente direccionais - Antenas <emphasis>altamente direccionais</emphasis> são usadas para ligações ponto-a-ponto; por exemplo entre dois edifícios. Este tipo de antenas propagam a uma longa distância um feixe espectro reduzido de luz, e são usualmente usados para ligações dedicadas."
+msgstr ""
+"Altamente direccionais - Antenas <emphasis>altamente direccionais</emphasis> "
+"são usadas para ligações ponto-a-ponto; por exemplo entre dois edifícios. "
+"Este tipo de antenas propagam a uma longa distância um feixe espectro "
+"reduzido de luz, e são usualmente usados para ligações dedicadas."
#. Tag: title
#, no-c-format
@@ -102,17 +168,45 @@
#. Tag: para
#, no-c-format, fuzzy
msgid "Clients typically connect in one of two modes: <emphasis>adhoc</emphasis> or <emphasis>infrastructure</emphasis>. Adhoc mode involves stations communicating directly with each other without the need for a central point to manage communications. This is also known as peer-to-peer mode. The default and most common mode is known as Infrastructure mode. Infrastructure mode uses a Wireless Access Point (WAP), which is a central device that manages transmissions between clients. Refer to the following for more details on Access Points:"
-msgstr "Os clientes tipicamente efectuam uma ligação através de dois modos: <emphasis>adhoc</emphasis> ou <emphasis>infraestruturas</emphasis>. O modo Adhoc envolve estações de comunicações que comunicam directamente umas com as outras sem que seja necessário um ponto central que efectue a gestão das comunicações. Este modo também é conhecido por modo ponto-a-ponto. Por omissão o modo mais comum conhecido é o modo de infraestrutura. O modo de infrasestrutura usado é o WAP (Ponto acesso sem fios), que é um dispositivo central que gere as transmissões entre clientes. Consultar o ponto seguinte para mais detalhes sobre pontos de acesso:"
+msgstr ""
+"Os clientes tipicamente efectuam uma ligação através de dois modos: "
+"<emphasis>adhoc</emphasis> ou <emphasis>infraestruturas</emphasis>. O modo "
+"Adhoc envolve estações de comunicações que comunicam directamente umas com "
+"as outras sem que seja necessário um ponto central que efectue a gestão das "
+"comunicações. Este modo também é conhecido por modo ponto-a-ponto. Por "
+"omissão o modo mais comum conhecido é o modo de infraestrutura. O modo de "
+"infrasestrutura usado é o WAP (Ponto acesso sem fios), que é um dispositivo "
+"central que gere as transmissões entre clientes. Consultar o ponto seguinte "
+"para mais detalhes sobre pontos de acesso:"
#. Tag: para
#, no-c-format, fuzzy
msgid "From <ulink url=\"http://en.wikipedia.org/wiki/Wireless_access_point\">Wikipedia.org</ulink>: <emphasis>In computer networking, a wireless access point (WAP) is a device that allows wireless communication devices to connect to a wireless network using Wi-Fi, Bluetooth or related standards. The WAP usually connects to a wired network, and can relay data between the wireless devices (such as computers or printers) and wired devices on the network.</emphasis>"
-msgstr "No endereço <ulink url=\"http://en.wikipedia.org/wiki/Wireless_access_point\">Wikipedia.org</ulink>:<emphasis>numa rede de computadores, o ponto de acesso sem fios (WAP) é um dispositivo que permite que dispositivos sem fios se liguem a uma rede sem fios utilizando standards Wi-Fi, Bluetooth ou outros relacionados. O WAP normalmente efectua a conexão a uma rede de cabo, e consegue retransmitir informação entre dispositivo sem fios (tais como computadores ou impressoras) e dispositivos ligados por cabo na rede.</emphasis>"
+msgstr ""
+"No endereço <ulink url=\"http://en.wikipedia.org/wiki/Wireless_access_point\">"
+"Wikipedia.org</ulink>:<emphasis>numa rede de computadores, o ponto de acesso "
+"sem fios (WAP) é um dispositivo que permite que dispositivos sem fios se "
+"liguem a uma rede sem fios utilizando standards Wi-Fi, Bluetooth ou outros "
+"relacionados. O WAP normalmente efectua a conexão a uma rede de cabo, e "
+"consegue retransmitir informação entre dispositivo sem fios (tais como "
+"computadores ou impressoras) e dispositivos ligados por cabo na "
+"rede.</emphasis>"
#. Tag: para
#, no-c-format, fuzzy
msgid "Access points commonly found in home environments provide different features from those found in business or corporate settings. Consumer-level WAPs are often integrated into broadband gateways, and multiple functions can be served from a single device. These functions typically include a switch for wired access, routing functionality, a broadband modem, and a network firewall. Usually an omnidirectional antenna is used, or multiple antennas, a scheme known as <emphasis>antenna diversity</emphasis>. WAPs often have a built-in web interface for their configuration which can be accessed by a web browser."
-msgstr "Os pontos de acesso geralmente encontrados em ambientes domésticos disponibilizam funcionalidades diferentes daqueles encontrados em ambientes de negócios ou empresas. WAPs do nível de consumidor são frequentemente integrados em gateways de banda larga, e numerosas funções podem ser servidos a partir de um único dispositivo. Estas funções tipicamente incluem um comutador para o acesso com fios, funcionalidade de roteamento, modem de banda larga, e uma Firewall da Rede. Usualmente uma antena omnidireccional é usada, ou múltiplas antenas, um esquema conhecido como <emphasis>diversidade de antena</emphasis>. WAPs muitas vezes têm uma interface baseada em navegadores para as configurações através da qual se acede via navegador web."
+msgstr ""
+"Os pontos de acesso geralmente encontrados em ambientes domésticos "
+"disponibilizam funcionalidades diferentes daqueles encontrados em ambientes "
+"de negócios ou empresas. WAPs do nível de consumidor são frequentemente "
+"integrados em gateways de banda larga, e numerosas funções podem ser "
+"servidos a partir de um único dispositivo. Estas funções tipicamente incluem "
+"um comutador para o acesso com fios, funcionalidade de roteamento, modem de "
+"banda larga, e uma Firewall da Rede. Usualmente uma antena omnidireccional "
+"é usada, ou múltiplas antenas, um esquema conhecido como "
+"<emphasis>diversidade de antena</emphasis>. WAPs muitas vezes têm uma "
+"interface baseada em navegadores para as configurações através da qual se "
+"acede via navegador web."
#. Tag: title
#, no-c-format
@@ -123,7 +217,24 @@
#, no-c-format
msgid "802.11b and 802.11g (the most common) devices are usually referred to as operating at 2.4GHz (gigahertz). In fact, the signals for these devices can operate on one of eleven (11) distinct sections (or <emphasis>channels</emphasis>) within the 2.4GHz band. Some regions allow operation in thirteen (13) channels, however the U.S FCC defines eleven (11) channels. What this means is that you can configure your wireless adapter and access point to operate on slightly different frequencies than other networks in your area, to avoid interference and congestion. Each of these channels cover a frequency range of 22MHz; in other words, a device operating in each of these channels can operate at up to 11MHz on either side of the "center" frequencies listed in the following table."
msgstr ""
+"Os dispositivos (mais comuns) 802.11b e 802.11g operam geralmente na "
+"frequência dos 2,4 GHz (gigahertz). De facto, os sinais para estes "
+"dispositivos podem operar numa das onze (11) distintas secções (ou "
+"<emphasis>canais</emphasis> dentro da banda 2.4GHz. Em determinadas regiões "
+"é permitido operações em treze (13) canais, no entanto o U.S FCC define onze "
+"(11) canais. Significa que pode configurar o adaptador sem fios e o ponto "
+"de acesso para operarem em frequências ligeiramente diferentes que as outras "
+"redes na sua área, para evitar interferências e congestionamento. Cada um "
+"desses canais cobre uma faixa de frequência de 22MHz; por outras palavras, a "
+"utilização de dispositivos em cada um desses canais pode operar até 11MHz "
+"em ambos os lados do "centro" frequências listadas na tabela a "
+"seguir."
+#. Tag: title
+#, no-c-format, fuzzy
+msgid "IEE 802.11b and 802.11g Channel Frequencies"
+msgstr "Frequências de Canal IEE 802.11b and 802.11g"
+
#. Tag: entry
#, no-c-format
msgid "Channel number"
@@ -240,16 +351,17 @@
msgstr "11"
#. Tag: para
-#, no-c-format
+#, no-c-format, fuzzy
msgid "If we study the frequencies used in these eleven (11) channels, and take into account that each channel can operate in 11MHz ranges either side (+/-) of its center frequency, the channels 1, 6 and 11 never overlap with each other. Channels that are separated by at least five other channels (or at least 2.5MHz) do not overlap. You can use this important piece of knowledge when you have wireless congestion issues; for example, in an apartment building with three wireless networks near each other, you can avoid congestion by getting the networks to run on channels that are sufficiently separated from each other, such as 1, 6 and 11. A heavily congested area may not provide the freedom to do this, however it is a useful thing to remember."
msgstr ""
-
-#. Tag: para
-#, no-c-format
-msgid "This chapter gives an overview of some of the hardware available for wireless LANs, the role they play, and further details about their operation."
-msgstr "Este capítulo apresenta uma visão geral de algum hardware disponível para LANs sem fios, o papel que desempenham, e detalhes adicionais sobre o seu funcionamento."
-
-#. Tag: title
-#, no-c-format
-msgid "IEE 802.11b and 802.11g Channel Frequencies"
-msgstr "Canais de frequências do IEE 802.11b e 802.11g"
+"Se estudarmos as frequências utilizadas nestes 11 (onze) canais, e levar em "
+"conta que cada canal pode operar no comprimento de onda dos 11MHz ou (+/-) "
+"ao lado do seu centro de frequência, os canais 1, 6 e 11 nunca se sobrepõem "
+"uns com os outros . Os canais que estão separados por pelo menos cinco "
+"outros canais (ou pelo menos por uma diferença de 2.5MHz de frequência) não "
+"se sobrepõem. Pode usar esta importante peça de conhecimento, quando tem "
+"problemas de congestionamento sem fio, por exemplo, em um prédio com três "
+"redes wireless próximas umas das outras, pode evitar o congestionamento das "
+"redes ao utilizar canais que são suficientemente separados uns dos outros, "
+"como 1, 6 e 11. Uma área bastante congestionada pode não proporcionar a "
+"liberdade de fazer isso, mas é uma coisa útil para se lembrar."
commit 3e04150d03b79c017a1562e584e5d9a171a26e8c
Author: Christopher Antila <crantila(a)fedoraproject.org>
Date: Fri Jul 30 03:27:56 2010 -0400
added Solfege, SuperCollider (main, programming, composing, exporting), Frescobaldi, LilyPond (main, syntax, counterpoint, piano, orchestra)
en-US/Frescobaldi.xml | 94 +
en-US/LilyPond/LilyPond-counterpoint.xml | 129 +
en-US/LilyPond/LilyPond-orchestra.xml | 279 ++
en-US/LilyPond/LilyPond-piano.xml | 303 +++
en-US/LilyPond/LilyPond-syntax.xml | 305 +++
en-US/LilyPond/LilyPond.xml | 74 +
en-US/Musicians_Guide.xml | 25 +-
en-US/Solfege.xml | 490 ++++
.../SuperCollider-Basic_Programming.xml | 2805 ++++++++++++++++++++
en-US/SuperCollider/SuperCollider-Composing.xml | 576 ++++
en-US/SuperCollider/SuperCollider-Exporting.xml | 46 +
en-US/SuperCollider/SuperCollider.xml | 206 ++
12 files changed, 5326 insertions(+), 6 deletions(-)
---
diff --git a/en-US/Frescobaldi.xml b/en-US/Frescobaldi.xml
new file mode 100644
index 0000000..7bd8068
--- /dev/null
+++ b/en-US/Frescobaldi.xml
@@ -0,0 +1,94 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<chapter id="chap-Musicians_Guide-Frescobaldi">
+ <title>Frescobaldi</title>
+ <para>
+ Frescobaldi is an advanced text editor, designed specifically for use with LilyPond source files. Its interface has been crafted in such a way that it aids the average workflow of creating and editing musical scores in LilyPond. Frescobaldi's tight integration with various system tools is similar to the way LilyPond itself is tightly integrated with various other software programs.
+ </para>
+ <para>
+ Frescobaldi is designed to take advantage of several features of the KDE 4 desktop system. Regular KDE users will immediately recognize Frescobaldi's components as being identical to several other key KDE applications - specifically Kate, Okular, and Konqueror. The key advantage to this approach is that KDE users will already know how to use most of the features of Frescobaldi, because those other applications are not just replicated, but actually used by Frescobaldi. There are many other advantages to this development approach.
+ </para>
+ <para>
+ For non-KDE users - especially those with older computers, this KDE-based approach may be more of a hassle than a help. An unfortunate side-effect of this development choice is that Frescobaldi has many "dependencies" in KDE packages, meaning that some KDE software will need to be installed in order to use Frescobaldi. This is a significant disadvantage for some users, but the benefits of using Frescobaldi far outweigh the extra hard drive space that will be required.
+ </para>
+
+ <section id="sect-Musicians_Guide-Frescobaldi-Makes_LilyPond_Easier">
+ <title>Frescobaldi Makes LilyPond Easier</title>
+ <para>
+ Using LilyPond with Frescobaldi is the recommended method for this User Guide. All three case studies in the "LilyPond" chapter (link? maybe?) use Frescobaldi. This is because the writers feel that Frescobaldi truly makes using LilyPond an easier thing to do.
+ </para>
+ <para>
+ Here are some of the benefits:
+ <itemizedlist>
+ <listitem><para>The text-editing component (from Kate), PDF-preview component (from Okular), and help file component (from Konqueror) are from applications that you may already know how to use.</para></listitem>
+ <listitem><para>The one-window setup of the application allows you to view either the source file and its output, or the source file and a help document, side-by-side. This is perfect for today's widescreen monitors.</para></listitem>
+ <listitem><para>The "Setup new score" tool greatly increases the speed of creating a new score, and offers some advanced configuration options that might otherwise take hours to discover.</para></listitem>
+ <listitem><para>The "Quick Insert" sidebar on the left-hand side of the window makes it easy to insert articulation, trill, and other marks. These would often otherwise require checking a reference document.</para></listitem>
+ <listitem><para>The 'LilyPond' menu provides several further tools to help adjust and troubleshoot your scores.</para></listitem>
+ <listitem><para>Careful integration with system tools allows you to input notes with a MIDI keyboard, listen to the MIDI output of your LilyPond score, and print the PDF file of your score, all from within Frescobaldi. These features are not covered in this Guide.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ For further information on Frescobaldi, please refer to the project's [http://www.frescobaldi.org/ website].
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-Frescobaldi-Installation">
+ <title>Installation</title>
+ <procedure>
+ <step><para>Run <code>sudo -c 'yum install frescobaldi'</code> or install the "frescobaldi" package with PackageKit or KPackageKit.</para></step>
+ <step><para>There are a lot of dependencies, including perl-* packages, subversion, kde* packages, and timidity++ including fluid-soundfont-gm (which is 114 MB)</para></step>
+ <step><para>Review and approve the list of dependencies.</para></step>
+ <step><para>The application can be found in the K Menu under 'Multimedia' or somewhere in the GNOME 'Applications' menu (probably under 'Multimedia'... for some reason)</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-Frescobaldi-Configuration">
+ <title>Configuration</title>
+ <para>
+ Changing these default settings is not necessary, but it may result in a more productive experience.
+ </para>
+ <procedure>
+ <step><para>Go to 'Settings > Configure Frescobaldi'</para></step>
+ <step><para>In 'General Preferences' check 'Save document when LilyPond is run', or else you will have to save it manually</para></step>
+ <step><para>Review the other options on this page</para></step>
+ <step><para>In 'Paths', only some of the fields will be filled; this is okay.
+ <itemizedlist>
+ <listitem><para>GNOME users might want to set "PDF Viewer" to 'evince'; this will not change the embedded PDF viewer, but it will change what opens when you click "Open PDF" in the bottom pane's 'LilyPond Log'. If left blank, this will open KDE's "Okular".</para></listitem>
+ <listitem><para>You can fill in the "MIDI Player" path, so that the "Play MIDI" button will work
+ <itemizedlist>
+ <listitem><para>The program "pmidi" is available from the Planet CCRMA at Home repositories, and is a command-line MIDI player; install it with yum; run 'pmidi -l' to see which ports are available; then put "pmidi -p 14:0" in the "MIDI Player" field where "14:0" is instead whatever port you want to use; you'll need a MIDI synthesizer (like FluidSynth) listening</para></listitem>
+ <listitem><para>or you can use timidity++</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem><para>You can change the "Default Directory" to the place where you store your LilyPond files</para></listitem>
+ <listitem><para>You can change "LilyPond documentation" if you don't want the right-side-bar "LilyPond Documentation" thing to internet it every time
+ <itemizedlist>
+ <listitem><para>install the 'lilypond-doc' package (it's 44 MB)</para></listitem>
+ <listitem><para>put "/usr/share/doc/lilypond-doc-2.12.2/index.html" in the field (or in another language if that's what you want)</para></listitem>
+ <listitem><para>this will need to be updated when LilyPond is updated; if you don't update it, then the built-in "LilyPond Documentation" tab will simply show up blank, instead of with the user guide - so it's harmless if you forget to update</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ </itemizedlist></para>
+ </step>
+ <step><para>options for the "Editor Component" are the same as those for KWrite</para>
+ <itemizedlist>
+ <listitem><para>I recommend going to the Editing tab, then "Auto Completion" and ensuring that both boxes are un-checked</para></listitem>
+ <listitem><para>You may want to change other settings here; highly-flexible, customizable, powerful; applies only in Frescobaldi</para></listitem>
+ </itemizedlist>
+ </step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-Frescobaldi-Using">
+ <title>Using Frescobaldi</title>
+ <para>
+ The practical use of Frescobaldi for editing LilyPond source files is described in the "LilyPond" chapter of this Guide, available [[User:Crantila/FSC/Typesetting/LilyPond|here]].
+ </para>
+ </section>
+
+</chapter>
diff --git a/en-US/LilyPond/LilyPond-counterpoint.xml b/en-US/LilyPond/LilyPond-counterpoint.xml
new file mode 100644
index 0000000..6800258
--- /dev/null
+++ b/en-US/LilyPond/LilyPond-counterpoint.xml
@@ -0,0 +1,129 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<section id="sect-Musicians_Guide-LilyPond-Counterpoint">
+ <title>Working on a Counterpoint Exercise (Tutorial)</title>
+ <para>
+ Imagine you're in Counterpoint class, and you've been asked to submit a very clean copy of your next assignment. Since you don't want to pay $450,000 for a commercially-available engraving solution and a fruity computer to use it, you decide that LilyPond is the solution for you.
+ </para>
+
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Tutorial_Files">
+ <title>Tutorial Files</title>
+ <para>
+ * [[User:Crantila/FSC/Typesetting/LilyPond/Counterpoint|Counterpoint (LilyPond)]]
+ * [[File:FSC-counterpoint.pdf]]
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Starting_the_Score">
+ <title>Starting the Score</title>
+ <procedure>
+ <step><para>Open Frescobaldi into a blank document</para></step>
+ <step><para>Use the 'LilyPond > Setup New Score' dialogue</para></step>
+ <step><para>Set the title and composer (and any other field) on the 'Titles and Headers' tab</para></step>
+ <step><para>You need a two staves, so you go to 'Parts' then 'Keyboard' then 'Piano'</para></step>
+ <step><para>You need to label the intervals between the notes, so you choose 'Special' then 'Figured Bass' (we'll put it in the right spot later</para></step>
+ <step><para>You go to the 'Score settings' tab</para>
+ <substeps>
+ <step><para>since you've already played through this example, uncheck "Create MIDI output" and save processing time</para></step>
+ <step><para>your example is in F Major</para></step>
+ <step><para>You want only whole notes, with no barlines; choose a 4/4 time signature, since we'll change this later.</para></step>
+ </substeps>
+ </step>
+ <step><para>Press 'Try' to get a preview of the score setup - the notes are demonstrative and will not be there</para></step>
+ <step><para>If the setup looks like you want it, then press 'OK' to generate the template</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Adjusting_Frescobaldis_Output">
+ <title>Adjusting Frescobaldi's Output</title>
+ <para>
+ For this tutorial, Frescobaldi's default output is good enough.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Inputting">
+ <title>Inputting</title>
+ <procedure>
+ <step><para>Look over the template. It's not important to understand what any of this means, but it's good if you can figure it out.</para></step>
+ <step><para>The piano's upper staff will contain the notes between the { and } following the " right = \relative c'' " portion</para></step>
+ <step><para>The piano's lower ... left</para></step>
+ <step><para>The figured bass will say what you put in figBass</para></step>
+ <step><para>start with the piano's upper part. Input "f1 g a f d e f c a f g f" (explain)</para></step>
+ <step><para>Check that it's right. Preview by press the "LilyPond" button on the toolbar</para></step>
+ <step><para>The exercise starts too high, and it ends too low. Change the starting pitch by " right = \relative c' "</para></step>
+ <step><para>Preview again; of course, it still ends too low (these simple exercises usually start and end on the same pitch).</para></step>
+ <step><para>Put a ' right after the c so that it goes to the upper C</para></step>
+ <step><para>Preview again, and this time it's right.</para></step>
+ <step><para>Now, enter the notes that you've written for the piano's lower staff: "f1 e d c bes c bes f d bes e f"</para></step>
+ <step><para>Preview the output again, and see that it starts too high, but ends on the right pitch.</para></step>
+ <step><para>Fix the start-too-high by changing to " left = \relative c { "</para></step>
+ <step><para>Preview again, and decide where to fix the other change (NB: I end up with "f1 e d c bes c bes f' d bes e f"</para></step>
+ <step><para>Enter the interval number between the top and bottom between the { and } preceded by " figBass = \figuremode "</para></step>
+ <step><para>You have to put each interval between < > brackets. The note-length of the figure's duration goes after the >, so I end up with "<1>1 <3> <5> <4> <3> <3> <5> <5> <5> <5> <3> <1>"</para></step>
+ <step><para>Now you realize that there are some signficant errors in your work. The top staff is the cantus, and cannot change. You have to correct the lower staff.</para></step>
+ <step><para>I've ended up with a lower part that is "f1 e d a bes c d e f d c f", which gives figures that are "<1>1 <3> <5> <6> <3> <3> <3> <6> <3> <3> <5> <1>"</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Formatting_the_Score">
+ <title>Formatting the Score</title>
+ <para>
+ We recommend formatting the score after the notes have been inputting. Formatting after inputting helps you avoid making formatting errors. LilyPond works effectively with this approach.
+ </para>
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Move_the_Figured_Bass">
+ <title>Move the Figured Bass</title>
+ <para>
+ Normally, figured bass parts are below the staves. This example is using the figured-bass feature of LilyPond to do something else, so we're going to move the figured bass so that it's where it needs to be.
+ </para>
+ <procedure>
+ <step><para>the \score{ } section contains everything in the score; notice that the figured bass has the identifier \bassFiguresPart; remove this</para></step>
+ <step><para>scroll up to where it says "bassFiguresPart = ... " and comment it with %</para></step>
+ <step><para>scroll up to where it says "pianoPart = ... " and enter the "\new FiguredBass \figBass" line that you just commented out, on a line between the "right" and "left" staves</para></step>
+ <step><para>now erase the part that you commented in (2) (or leave it there)</para></step>
+ <step><para>Preview the file, and see that the figures now appear between the piano staves</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Remove_the_Word_Piano">
+ <title>Remove the Word "Piano" at the Start</title>
+ <procedure>
+ <step><para>Find the part that begins "pianoPart = ... " and erase the "instrumentName ... " line (or comment it)</para></step>
+ <step><para>Preview the file, and see that it no longer says, "Piano"</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Counterpoint-Make_some_Elements_Transparent">
+ <title>Make some Elements Transparent</title>
+ <para>
+ This involves some more advanced tweaking. Explain this sort of command.
+ </para>
+ <para>
+ Every layout object has a "stencil" property. By default, this is set to whatever function draws the object. If you set that property to #f, which means "false", then the drawing function is not called, and the object will not appear on the score.
+ </para>
+ <para>
+ Every layout object also has a "transparent" property. By default, this is set to #f ("false"). Setting it to #t ("true") will make the object transparent.
+ </para>
+ <para>
+ You can use "\once \override ..." or \revert ..." too
+ </para>
+ <procedure>
+ <step><para>Find the "global" section</para></step>
+ <step><para>After \key and \time, put " \override Score.BarLine #'stencil = ##f "</para></step>
+ <step><para>Preview the file, and see that this doesn't work quite as intended.</para></step>
+ <step><para>It so happens that, while measure lines within a staff are handled by Staff.BarLine, measure lines between staves are handled by Staff.SpanBar; so you'll need to set its 'transparent symbol to #t also</para></step>
+ <step><para>But there's still no measure-line at the end! You want a barline at the end, so pick one of the staves (right, left, figBass - it doesn't matter in this case) and use the \revert command (don't know if I should put this in, but: "\revert Score.BarLine #'transparent and \revert Score.SpanBar #'transparent")</para></step>
+ <step><para>But even this isn't quite right. You want a double-barline at the end. So, put the cursor after the \revert lines, and then from the menu, 'LilyPond > Bar Lines > Ending Bar Line' . It knows what you want, remembers the symbol for you, so you don't have to!</para></step>
+ </procedure>
+ <para>
+ <itemizedlist>
+ <listitem><para>explain in there the difference between a Staff.* and Score.* override</para></listitem>
+ <listitem><para>Unlike with some other elements, if you simply remove the "\time 4/4" indicator, it will still print the default 4/4 time signature.</para></listitem>
+ <listitem><para>This example is musically simple, but it includes some advanced concepts, and importantly helps to get over a couple of common (and understandable) fears, especially for beginners, and especially for musically-simple things like this</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ </section>
+
+</section>
diff --git a/en-US/LilyPond/LilyPond-orchestra.xml b/en-US/LilyPond/LilyPond-orchestra.xml
new file mode 100644
index 0000000..43b1217
--- /dev/null
+++ b/en-US/LilyPond/LilyPond-orchestra.xml
@@ -0,0 +1,279 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<section id="sect-Musicians_Guide-LilyPond-Orchestra">
+ <title>Working on an Orchestral Score (Tutorial)</title>
+ <para>
+ Scenario: You volunteer at a community orchestra, and the conductor decides to play a Haydn symphony. The orchestra does not own any Haydn symphonies, so the conductor asks you if you can help to find a full score and parts. You find a book with the conductor's score, but no parts. You decide to input the score in LilyPond, which will allow you to easily create the missing parts.
+ </para>
+ <para>
+ This tutorial uses the first movement of Joseph Haydn's "Sinfonia No. 92: Oxford."
+ </para>
+ <para>
+ When following this tutorial, it is recommended that the reader follows along, creating their replica of this tutorial's PDF.
+ </para>
+
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Tutorial_Files">
+ <title>Tutorial Files</title>
+ <para>
+ * [[User:Crantila/FSC/Typesetting/LilyPond/Orchestra|Orchestra (LilyPond)]]
+ * [[File:FSC-orchestra.pdf]]
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Starting_the_Score">
+ <title>Starting the Score</title>
+ <!-- !! You added an additional staff for the 2nd oboe, which isn't in some of these instructions !! -->
+ <procedure>
+ <step><para>'LilyPond > Setup New Score'</para></step>
+ <step><para>"Titles and Headers" Tab:</para>
+ <itemizedlist>
+ <listitem><para>Dedication: Comte d'Ogny and Prince Oettingen-Wallerstein</para></listitem>
+ <listitem><para>Title: Sinfonia No. 92</para></listitem>
+ <listitem><para>Subtitle: "Oxford"</para></listitem>
+ <listitem><para>Composer: Haydn, Joseph</para></listitem>
+ <listitem><para>all the rest are blank</para></listitem>
+ </itemizedlist>
+ </step>
+ <step><para>"Parts" Tab:</para>
+ <itemizedlist>
+ <listitem><para>Flute, 2 of Oboe, Bassoon</para></listitem>
+ <listitem><para>Horn in F, Trumpet in C</para></listitem>
+ <listitem><para>Timpani</para></listitem>
+ <listitem><para>Violin, Violin, Viola, Cello, Contrabass</para></listitem>
+ </itemizedlist>
+ </step>
+ <step><para>"Score settings" Tab:</para>
+ <itemizedlist>
+ <listitem><para>Key signature: G Major</para></listitem>
+ <listitem><para>Time signature: 3/4</para></listitem>
+ <listitem><para>Tempo indication: Adagio</para></listitem>
+ <listitem><para>other settings as desired; I recommend not remocing bar numbers, and removing the default tagline</para></listitem>
+ </itemizedlist>
+ </step>
+ <step><para>Click "Try" to see if it works. The instrument names will not be the same as the PDF score. This will be fixed later.</para></step>
+ <step><para>Click "OK" to generate the score.</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Adjusting_Frescobaldis_Output">
+ <title>Adjusting Frescobaldi's Output</title>
+ <!-- Part of this portion is shared with the Piano example -->
+ <para>
+ These steps are useful in establishing a consistent input style for LilyPond. The things suggested here are also useful for getting used to working with large scores, which can be a challenge in any text editor. Thankfully, careful (and consistent!) code organization goes a long way in helping you to quickly find your way around your files. Setting up files the right way to begin with makes this much easier in the end.
+ </para>
+ <para>
+ When you first setup the score, Frescobaldi will have created many sections for you by default. The program avoids making too many stylistic choices for you, which allows you to create your own style. It also sets up the default sections in a logical way:
+ [pre]version
+ header
+ widely-used settings like tempoMark and "global"
+ individual parts
+ score formatting[/pre]
+ The specific ordering will become more obvious to you as you get used to LilyPond.
+ </para>
+ <para>
+ Here are some of the things that I do before inputting notes:
+ <itemizedlist>
+ <listitem><para>Use section-dividers (like <code>%%%%%%%% NOTES %%%%%%%%</code> for individual parts) to demarcate sections.</para></listitem>
+ <listitem><para>Use different levels of dividers (like <code>%%%% OBOE %%%%</code> for the oboe) to show sub-sections</para></listitem>
+ <listitem><para>Add blank lines between large sections, to separate them more obviously</para></listitem>
+ <listitem><para>Begin braces on new lines, like
+ [pre]\header
+ {
+ title = "Symphony"
+ ...
+ }
+ [/pre] instead of on the same line, like
+ [pre]\header {
+ title = "Symphony"
+ ...
+ }
+ [/pre] This is simply a matter of personal taste, resulting from prior experience with C and C-like programming languages.</para></listitem>
+ <listitem><para>Familiarize myself with the sections and commands created by Frescobaldi, getting a sense of what the section/command does (even if I don't understand what each specific command does). This makes it easier to sort out problems and customization down the road. Sometimes, when the setup is quite complex, I make comments about what seems to be going on.</para></listitem>
+ <!-- End the portion taken from the Piano example -->
+ <listitem><para>Change the instrument names to replicate what my score indicates. You don't necessarily need to do this, so long as the people using your score will understand what the instruments are. Since my goal is to replicate this Dover edition score, I will change the names.</para>
+ <procedure>
+ <step><para>In the "PARTS" section, each xPart section has an "instrumentName = "something"" field.</para></step>
+ <step><para>We'll be changing those to the following Italian names:</para>
+ <itemizedlist>
+ <listitem><para>Flute --> Flauto</para></listitem>
+ <listitem><para>Oboe I --> I Oboe</para></listitem>
+ <listitem><para>Oboe II --> II Oboe</para></listitem>
+ <listitem><para>Bassoon --> 2 Fagotti</para></listitem>
+ <listitem><para>Horn in F --> 2 Corni in Sol (NB: these would have been "natural horns")</para></listitem>
+ <listitem><para>Trumpet in C --> 2 Clarini in Do (NB: a clarino is a kind of trumpet)</para></listitem>
+ <listitem><para>Violin I --> Violino I</para></listitem>
+ <listitem><para>Violin II --> Violino II</para></listitem>
+ <listitem><para>Cello --> Violoncello obligato</para></listitem>
+ <listitem><para>Contrabass --> Basso</para></listitem>
+ </itemizedlist>
+ </step>
+ <step><para>Now we have to change the horns' transposition to match the name. This is because Frescobaldi added a "Horn in F" part, which is the most common horn transposition. However, Haydn's score uses horns in G (or "Sol" in Italian).</para></step>
+ <step><para>Scroll up to the "hornF" section under the NOTES marker. Change the line <code>\transposition f</code> to <code>\transposition g</code>.</para></step>
+ <step><para>As it turns out, transposition can be a little more complicated than that. We'll deal with that when we get there.</para></step>
+ </procedure>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Inputting">
+ <title>Inputting</title>
+ <para>
+ This tutorial offers step-by-step instructions representing one way to input the score. Only the part before "Allegretto" will be inputted. The full first movement is included in the PDF file, so you can input it yourself.
+ </para>
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Inputting-Start_with_the_Easy_Part">
+ <title>Starting with the Easy Part</title>
+ <para>
+ The best way to get started on large scores is to just start with something easy. Nothing can be easier than doing nothing, so let's first input the multi-measure rests in the wind sections and timpani.
+ </para>
+ <procedure>
+ <step><para>Count the number of measures of rests. In this case, all of the winds and the timpani have thirteen or more measures of rests before their first entrance.</para></step>
+ <step><para>Let's put in those thirteen measures first.</para>
+ <procedure>
+ <step><para>In the NOTES section, find the flute section, and put in <code>R2.*13 |</code>.</para></step>
+ <step><para>Here is an explanation of R</para></step>
+ <step><para>here is an explanation of |</para></step>
+ <step><para>Copy and past that into the rest of the winds and the timpani.</para></step>
+ </procedure>
+ </step>
+ <step><para>The timpani and trumpet/clarini parts have six further full measures of rest, before the measure with a fermata. The fermata can't be included in the multi-measure rest, so we'll treat it separately. Add <code>R2.*6 |</code> to the timpani and trumpets parts.</para></step>
+ <step><para>The horns, bassoons, and second oboe have one further measure of rests, so add <code>R2. |</code> to those parts. We won't use <code>r2. |</code> because yadda.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Inputting-Wind_and_Timpani">
+ <title>Continuing with the Wind and Timpani Parts</title>
+ <procedure>
+ <step><para>Now we need to start adding notes. We'll start with the parts that have only rests:</para>
+ <substeps>
+ <step><para>The trumpets and timpani have no notes in the slow introduction, so all they need is the three-beat measure with a fermata on the third beat.</para></step>
+ <step><para>Rests are notated as though they were a pitch called "r". That is to say, if you want to input a rest, then you input the pitch r. This three-quarter-rest measure will be notated as <code>r4 r r |</code>. Put this into the trumpets and timpani parts. Remember: it's always a good idea to indicate the duration at the beginning of a measure, but it's not necessary to indicate a repeated duration.</para></step>
+ <step><para>Frescobaldi allows you to insert common musical signs with the "Quick Insert" tab on the left of the screen. It may be hidden; to show it, click "Quick Insert" on the left-most edge of the Frescobaldi window.</para></step>
+ <step><para>We need a regular fermata on the third quarter rest of this measure. So, place the text-input caret just after the third quarter rest, and click the fermata symbol in the "Quick Insert" toolbar-thing.</para></step>
+ <step><para>You should end up with <code>r4 r r\fermata |</code>.</para></step>
+ <step><para>While the word for a fermata symbol is easy to remember, other symbols have less-obvious LilyPond notations, so the "Quick Insert" toolbar-thing is very handy.</para></step>
+ <step><para>Copy this measure to the other part.</para></step>
+ </substeps>
+ </step>
+ <step><para>The next easiest part is the bassoons:</para>
+ <substeps>
+ <step><para>We've already input the bassoons' full-measure rests, so we can start with the first measure in which they play. It should be notated as <code>r8 d g bes d bes |</code>. Input this, and preview the score to see what happens.</para></step>
+ <step><para>Success! When first starting an instrument, it's important to check that the notes begin in the right register. If they don't, it can be adjusted easily by changing the pitch indication that follows the <code>\relative</code> declaration. In this case, the bassoon happened to be in the right register for us by default.</para></step>
+ <step><para>The next measure is <code>g8 cis cis4 r |</code>. Remember to indicate "cis" twice. Put it in and check that it's correct.</para></step>
+ <step><para>It is, but we're still missing some formatting. Use the "Quick Insert" toolbar-thing to add staccato markings to the first measure. You can add a staccato to the eighth-rest, but this doesn't make sense, so you shouldn't.</para></step>
+ <step><para>Slurs begin at ( and end at ). Add a slur from the g to c-sharp.</para></step>
+ <step><para>Preview the score to make sure that you entered these articulations correctly. Your code should be:
+ [pre]r8 d-. g-. bes-. d-. bes-. |
+ g8( cis) cis4 r |[/pre]</para></step>
+ </substeps>
+ </step>
+ <step><para>Now to add the "forte" marking. You can add text (or any object, for that matter) onto a note (or rest, etc.) with one of these three symbols:
+ <itemizedlist>
+ <listitem><para>^ meaning "put this above the object"</para></listitem>
+ <listitem><para>- meaning "put this above or below, as you think is best"</para></listitem>
+ <listitem><para>_ meaning "put this below the object"</para></listitem>
+ </itemizedlist>
+ As you saw earlier, Frescobaldi attached our staccato markings with the "as you think best" symbol, which is almost always the right choice for articulations. By convention, dynamic markings always go below the staff to which they apply, so we won't want to give LilyPond so much freedom, this time.
+ </para></step>
+ <step><para>The easiest way to add (unformatted) text to a note is to simply attach it in quotation marks. For the "forte" marking, put this on the eighth-rest: <code>r8_"f" etc.</code></para></step>
+ <step><para>When you preview this, you'll notice that the result is thoroughly underwhelming. It looks quite unlike a "forte" marking, and people reading the score would probably be confused, if just momentarily.</para></step>
+ <step><para>Thankfully, LilyPond provides a very easy and elegant way to input well-formatted dynamic markings. Change the eighth-rest to this: <code>r8\f etc.</code></para></step>
+ <step><para>When you preview this, you will see that it now looks exactly like a typical "forte" marking. Not all dynamic markings have these short-forms, but most do.</para></step>
+ <step><para>The "a 2" marking, meaning "to be played by two players," does need the text-in-quotes format, however. Put that marking ''above'' the d following the eighth rest.</para></step>
+ <step><para>Those two measures should now look like this:
+ [pre]r8\f d-.^"a 2" g-. bes-. d-. bes-. |
+ g8( cis) cis4 r |
+ [/pre]
+ Note that <code>d-.^"a 2"</code> gives the same result as <code>d^"a 2"-.</code></para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Inputting-Oboe_and_Horn">
+ <title>Oboe and Horn Parts</title>
+ <procedure>
+ <step><para>You now know enough to complete the oboe parts, and the flute part. Give it a try. Here are some tips, in case you get stuck:
+ <itemizedlist>
+ <listitem><para>You will need to adjust the range of the flute and oboe, to read <code>flute = \relative c'''</code> and <code>oboeI = \relative c'''</code></para></listitem>
+ <listitem><para>You may want to use [ and ] to control eighth-note beaming in the Oboe I and Flauto parts. You may not</para></listitem>
+ <listitem><para>The Flauto will need more multi-measure rests with R, ''after'' some of the notes are inputted.</para></listitem>
+ <listitem><para>All of the parts will end with the same three-quarter-note-rests-with-fermata measure.</para></listitem>
+ </itemizedlist>
+ </para></step>
+ <step><para>And now for the horns part. Transposing instruments pose a small problem for LilyPond, as with any human or computerized engraving tool. These steps first ensure that the transposition is set correctly.</para></step>
+ <step><para>The "hornF" section should already have a <code>\transposition g</code> segment from earlier. This tells LilyPond that the following notes are not in concert pitch, but rather are "in G." A transposition statement tells LilyPond, in absolute pitch, which pitch actually sounds when the player plays a written c' . In this case, the sound pitch is a perfect fourth below c' . If we wanted it to be a perfect fifth higher, then we would need to write <code>\transposition g'</code>, but that's not accurate for this case.</para></step>
+ <step><para>Our next obstacle is not actually a problem with LilyPond, but with how Frescobaldi set up the score for us. The score that we wish to notate does not have a written key signature for the horn, but the "global" section (near the top of the file) includes one: G Major. If this score were particularly complicated, or if it contained a large number of transposing instruments, then it would be best to remove the <code>\key ...</code> declration from the "global" section (and including it in every instrument as necessary). However, since there is only one transposing instrument, we might be better off simply removing the global from the horn.</para></step>
+ <step><para>do the rest of this stuff to get that done right</para></step>
+ <step><para>make a note in the global section of which instruments don't use it</para></step>
+ <step><para>While you're at it, do the same for the trumpets and timpani parts, which also do not use a printed key signature.</para></step>
+ <step><para>The other issue with the horn part is that two pitches are to be played at once, and they are both notated in the same voice. This is solved in the piano example like this: <code><g g'></code>. You can copy-and-paste this as needed.</para></step>
+ <step><para>You can now finish inputting the horn part.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Inputting-Strings">
+ <title>Moving on to the Strings</title>
+ <para>
+ After correctly finishing all of the wind and timpani parts, you can move on to the strings.
+ <itemizedlist>
+ <listitem><para>Input all of the pitches and note lengths first, then return to fill in the other markings.</para></listitem>
+ <listitem><para>If you get stuck, then put in some filler notes, and finish the rest of that part. Make a note for yourself, as a comment in the source file, so that you know to return later to finish the part.</para></listitem>
+ <listitem><para>If twenty measures at once is too many, then break it into smaller chunks and input those.</para></listitem>
+ <listitem><para>Here are some tips to help you through this passage. Use the LilyPond help files if you need further assistance.
+ <itemizedlist>
+ <listitem><para>Tuplets (Triplets):
+ <itemizedlist>
+ <listitem><para>To write any tuplet, use the formula <code>\times x/y { notes in here }</code>, where x is the number of notes actually space to use, and y is the number of notes to let you display.</para></listitem>
+ <listitem><para>For an eighth-note triplet that takes up one beat, you might use this: <code>\times 2/3 { c8 d e }</code>, because in the space of 2 eighth notes you want to fit three instead.</para></listitem>
+ <listitem><para>This is much more powerful than it seems at first. You might want to make it seem as though the measures have stopped being marked, and write something like <code>\times 4/40 { ... }</code>, which will allow you to fit forty of something into the number of beat usually occupied by four of them. This is especially useful with cadenzas, and cadenza-like passages.</para></listitem>
+ </itemizedlist></para></listitem>
+ <listitem><para>Short-term Polyphonic Input (Divisi):
+ <itemizedlist>
+ <listitem><para>Anything between << and >> is interpreted by LilyPond as happening together. If you take a look at the "score" section at the bottom of the file, you will see that all of the parts are listed in that kind of bracket. This ensures that they all happen simultaneously.</para></listitem>
+ <listitem><para>For short-term polyphonic input, use the formula [pre]<< { upper-voice notes } \\ { lower-voice notes } >>[/pre]. Remember that the "upper voice" has upward-pointing stems, and the "lower voice" has downward-pointing stems.</para></listitem>
+ </itemizedlist></para></listitem>
+ <listitem><para>Ties: These can be written by adding ~ to the end of the note beginning the tie: [pre]c4~ c8[/pre]</para></listitem>
+ <listitem><para>Grace Notes: These take up no logical time, and are smaller than ordinary notes. Any notes appearing <code>\grace { in here }</code> would be considered grace notes.</para></listitem>
+ <listitem><para>Crescendo and Diminuendo Markings:
+ <itemizedlist>
+ <listitem><para>These are added like other dynamic markings, attached with a backslash to the note where they begin. A crescendo is triggered with \< and a diminuendo with \>.</para></listitem>
+ <listitem><para>The left-most point of the marking (its beginning) is indicated by where you put \< or \></para></listitem>
+ <listitem><para>The right-most (or end-)point is indicated by either another dynamic marking of any sort, or the special cancellation character (<code>\!</code>).</para></listitem>
+ </itemizedlist></para></listitem>
+ <listitem><para>Italic "staccato" Text: <code>\markup { \italic { staccato } }</code></para></listitem>
+ <listitem><para>Source File Measure Numbers: One of the techniques that can be used when inputting larger scores is writing measure numbers into the source file as comments. I usually write measure numbers every five measures, but it depends on the speed of the music, and what seems like it's useful.</para></listitem>
+ </itemizedlist></para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Orchestra-Inputting-Fast_Section">
+ <title>To Continue to the Fast Section</title>
+ <para>
+ If you want to finish inputting the first movement, as an exercise, then you will also need to know how to write a tempo-change in an orchestral score:
+ </para>
+ <procedure>
+ <step><para>In order to continue, we'll need to include a special measure-line (barline) and a change-of-tempo indicator. This would be easy, and would display correctly, if we simply inputted the change in one particular voice. However, if we did that, the change would only appear in one of the orchestral parts exported from the score.</para></step>
+ <step><para>We're going to define a new whatever-thing, like the "global" section created for us by Frescobaldi, and include it in all of the parts.</para></step>
+ <step><para>The code needed for this is a little bit complicated, but you don't need to write it yourself: just take it from the "tempoMark" section created by Frescobaldi. All you need to do is change "Adagio" to "Allegro spiritoso," and add the barline indicator. This is also easy because of Frescobaldi: 'LilyPond > Bar Lines > Repeat start'</para></step>
+ <step><para>You end up with
+ [pre]startExposition =
+ {
+ \once \override Score.RehearsalMark #'self-alignment-X = #LEFT
+ \once \override Score.RehearsalMark #'break-align-symbols = #'(time-signature key-signature)
+ \mark \markup \bold "Allegro spiritoso"
+ \bar "|:"
+ }
+ [/pre]</para></step>
+ <step><para>Add the reference to this in all of your parts. Because of how I named it, this also serves as a handy way to find your way through the LilyPond markup file.
+ [pre] r4 r r\fermata |
+
+ \startExposition
+
+ R2.*4 |
+ [/pre]</para></step>
+ <step><para>The barline and tempo-change will not appear unless you write some music after them, so put in some or all of the rests that follow, just to test it.</para></step>
+ </procedure>
+ </section>
+ </section> <!-- End "Inputting" Section --> <!-- LilyPond-Orchestra-Inputting- -->
+
+</section>
diff --git a/en-US/LilyPond/LilyPond-piano.xml b/en-US/LilyPond/LilyPond-piano.xml
new file mode 100644
index 0000000..1572bcb
--- /dev/null
+++ b/en-US/LilyPond/LilyPond-piano.xml
@@ -0,0 +1,303 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<section id="sect-Musicians_Guide-LilyPond-Piano">
+ <title>Working on a Piano Score (Tutorial)</title>
+ <para>
+ Scenario: At a used music store, you encounter a 60-year-old, hand-engraved copy of a Schubert ''Impromptu'', but it's been badly damaged by a flood. The store's owner says that, if you can use the score, you can keep it for free. The score is barely legible, so you decide to prepare a copy with a computer notation program.
+ </para>
+ <para>
+ I'm using Schubert's ''Impromptu'' Op.90 (D.899) Nr.4, in A-flat major. Published by Edition Peters: 10463, ed. Walter Niemann. We'll be setting the A section (from the beginning to the Trio).
+ </para>
+ <para>
+ When following this tutorial, it is recommended that the reader follows along, creating their replica of this tutorial's PDF.
+ </para>
+
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Tutorial_Files">
+ <title>Links to Files for This Tutorial</title>
+ <para>
+ * [[User:Crantila/FSC/Typesetting/LilyPond/Piano|Piano (LilyPond)]]
+ * [[File:FSC-piano.pdf]]
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Starting_the_Score">
+ <title>Starting the Score</title>
+ <procedure>
+ <step><para>Open Frescobaldi with a new document.</para></step>
+ <step><para>Start the "Setup New Score" tool, by clicking 'LilyPond > Setup New Score' in the menu.</para></step>
+ <step><para>Fill in the following fields on the "Titles and Headers" tab:
+ <itemizedlist>
+ <listitem><para>Title: Impromptu</para></listitem>
+ <listitem><para>Compuser: Schubert, Franz</para></listitem>
+ <listitem><para>Opus: Opus 90/4</para></listitem>
+ </itemizedlist>
+ </para></step>
+ <step><para>Switch to the "Parts" tab:</para>
+ <substeps>
+ <step><para>From the "Available parts" list, select "Keyboard instruments"</para></step>
+ <step><para>Select "Piano"</para></step>
+ <step><para>Click "Add"</para></step>
+ <step><para>On the right-hand side of the window, it's possible to add multiple voices from the start. We won't be using this feature, because most of the score is not polyphonic. It is especially convenient in fugues.</para></step>
+ </substeps>
+ </step>
+ <step><para>Switch to the "Score settings" tab, and adjust the following settings:
+ <itemizedlist>
+ <listitem><para>Key signature: As Major</para></listitem>
+ <listitem><para>Time signature: 3/4</para></listitem>
+ <listitem><para>Tempo indication: Allegretto</para></listitem>
+ <listitem><para>Remove default tagline: checked</para></listitem>
+ <listitem><para>Adjust other settings as desired - it is recommended to keep the default pitch name language.</para></listitem>
+ </itemizedlist>
+ </para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Adjusting_Frescobaldis_Output">
+ <title>Adjusting Frescobaldi's Output</title>
+ <!-- This section is shared with the orchestral example -->
+ <para>
+ These steps are useful in establishing a consistent input style for LilyPond. The things suggested here are also useful for getting used to working with large scores, which can be a challenge in any text editor. Thankfully, careful (and consistent!) code organization goes a long way in helping you to quickly find your way around your files. Setting up files the right way to begin with makes this much easier in the end.
+ </para>
+ <para>
+ When you first setup the score, Frescobaldi will have created many sections for you by default. The program avoids making too many stylistic choices for you, which allows you to create your own style. It also sets up the default sections in a logical way:
+ [pre]version
+ header
+ widely-used settings like tempoMark and "global"
+ individual parts
+ score formatting[/pre]
+ The specific ordering will become more obvious to you as you get used to LilyPond.
+ </para>
+ <para>
+ Here are some of the things that I do before inputting notes:
+ <itemizedlist>
+ <listitem><para>Use section-dividers (like <code>%%%%%%%% NOTES %%%%%%%%</code> for individual parts) to demarcate sections.</para></listitem>
+ <listitem><para>Use different levels of dividers (like <code>%%%% RIGHT HAND %%%%</code> for the right hand) to show sub-sections</para></listitem>
+ <listitem><para>Add blank lines between large sections, to separate them more obviously</para></listitem>
+ <listitem><para>Begin braces on new lines (as [pre]\header
+ {
+ title = "Impromptu"
+ ...
+ }[/pre]instead of on the same line (as [pre]\header {
+ title = "Impromptu"
+ ...
+ }[/pre]This is simply a matter of personal taste, resulting from prior experience with C and C-like programming languages.</para></listitem>
+ <listitem><para>Familiarize myself with the sections and commands created by Frescobaldi, getting a sense of what the section/command does (even if I don't understand what each specific command does). This makes it easier to sort out problems and customization down the road. Sometimes, when the setup is quite complex, I make comments about what seems to be going on.</para></listitem>
+ <listitem><para>At this point, I also added the "Dynamics Context" commands, as described below in the "Piano Dynamics" section</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting">
+ <title>Inputting</title>
+ <para>
+ Piano scores present some unique challenges with LilyPond, but they're easy to overcome with some careful thought. This tutorial will avoid step-by-step instructions on how to input particular notes, instead focussing on those unique piano challenges presented in this particular composition. The LilyPond "Notation Reference" provides a section dedicated to keyboard and piano music. Most of the situations described there are not present or discussed in this score, which gives this tutorial unique material.
+ </para>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting-Order_of_Inputting">
+ <title>Order of Inputting</title>
+ <para>
+ Choosing the right order to input your scores can make things much easier to troubleshoot. Here are some suggestions:
+ </para>
+ <procedure>
+ <step><para>Input music in small sections at a time. Two, four, or eight measures is usually a good size, but it depends on the size of the composition, the size of its sections, and the form of the music. It doesn't make sense to input a passage of 9 whole-notes in stages of two measures, but two measures may be too long for passages composed primarily of 128th-notes.</para></step>
+ <step><para>Input one staff at a time, then check its accuracy using Frescobaldi's preview function (press the "LilyPond" button on the toolbar)</para>
+ <itemizedlist>
+ <listitem><para>Input the pitch and rhythms first, then slurs, articulations, ties, and fingerings. It's easier to correct errors with pitch and rhythm (and register!) before the extra markings are added.</para></listitem>
+ <listitem><para>To help make sixteenth-note passages easier to read, you can use double- or triple-spaces to separate beats. Such passages often feature repeated patterns; before copy-and-pasting, make sure that the pattern repetition is truly exact!</para></listitem>
+ </itemizedlist>
+ </step>
+ <step><para>When you progress to a new four-measure section (or two- or six-, etc.), input the less difficult staff first (if there is one). This way, you will have a better visual reference when verifying the more difficult part. It's easier to see differences if your score looks closer to the original.</para></step>
+ <step><para>The same idea applies for multi-measure polyphonic passages in the same staff: input the easier part first, so you have a visual reference.</para></step>
+ <step><para>To help ensure that you don't get lost, write measure numbers in the source file every five measures or so. See the example source file to see how this is done. Even if you don't want to have measure numbers in the final score, it can be helpful to include them during inputting and error-checking.</para></step>
+ <step><para>Save the dynamics and pedal markings for last! Sometimes, they can help you to keep your place in the score while double-checking that it's correct, but I don't usually put them in with the rest of the notes, for reasons described below in the "Piano Dynamics" section.</para></step>
+ </procedure>
+ <para>
+ Most importantly, remember that these are just suggestions! The order in which you do things should change depending on what suits you best. Different kinds of scores will require different strategies.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting-Chords">
+ <title>Chords</title>
+ <para>
+ There are two ways to input chords, but one will be used much more often.
+ </para>
+ <para>
+ This style of chord notation is more common: <code><as ces>4-_</code> Notice how only the pitches are notated inside the < > brackets, and everything else attached to the end. There is one exception to this: fingering should be indicated on the pitch associated with that finger: <code><as-1 ces-3>4-_</code> Not only does this help you to sort out what was probably intended, but it allows LilyPond to stack the fingering in the right order. When using "relative" entry mode, it is the lowest note of the chord that is taken into consideration when placing the next note.
+ </para>
+ <para>
+ This style of chord notation is less common: <code><<as4-> ces>></code> Notice how everything must be notated inside the << >> brackets. This can make it more difficult to read the chord in the source file, but it also allows much greater flexibility: only some chord members can have ties; certain chord members can last for longer than others; certain chord members can "break out" into or out of polyphonic passages. This notation is rarely ''needed'', but you may be inclined to over-use it if you are trying to exactly copy the look of a hand-engraved score. Like the "times" command for tuplets, this is one of LilyPond's deceptively powerful techniques. When using "relative" entry mode, it is the last note of the chord that is taken into consideration when placing the next note.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting-Fingering">
+ <title>Fingering</title>
+ <para>
+ LilyPond allows you to indicate fingering by attaching the digit number to a note as an articulation mark: <code>a16-5</code> will show a "5" as a fingering mark. As with all other articulation marks indicated in this way, you can use ^ or _ to instruct LilyPond to put the mark above or below the note, respectively. It is usually better to let LilyPond decide for itself by using a <code>-</code>.
+ </para>
+ <para>
+ When entering chords, it is recommended that you enter the fingering with the note to which it is attached, like <code><as-1 ces-4>4-_</code>. It is possible to enter this as <code><as ces>4-1-4-></code>, but this not only looks confusing, it may confuse LilyPond as to which digit is intended for which note.
+ </para>
+ <para>
+ Because the extra digits look like they indicate note-lengths, it is recommended to mark them consistently. For this same reason, it is also recommended that fingering marks be added to source files only after the pitch and rhythm have been double-checked. The source file included with this tutorial puts fingering marks after any other articulation and length marking.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting-Cautionary_Accidentals">
+ <title>Cautionary Accidentals</title>
+ <para>
+ Musical Definition:
+ This score makes some use of ''cautionary accidentals''. These are accidentals which don't change the pitches to be played, but rather are used as a precaution against forgetting that they are there. This usually happens when an accidental in the written key signature is changed for a significant number of measures, and then suddenly changes back. The cautionary accidental would be applied when the standard key signature returns, to remind the musician of the key signature.
+ </para>
+ <para>
+ LilyPond Notation:
+ These are notated in LilyPond with an exclamation mark placed before the note-value: <code>ces!16</code>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting-Changing_the_Style_of_Crescendo">
+ <title>Changing the Style of Crescendo</title>
+ <para>
+ Sometimes the composer or editor prefers to use the words "''crescendo''" or its abbreviation, "''cresc.''", instead of the angled-line < style of crescendo. In LilyPond these are handled by the same source-file notation (<code>\<</code> to start and <code>\!</code> to end explicitly). However, if you want to use text and a "spanner" (dotted or dashed line, for example) instead of the < sign, you need to tell LilyPond. This can be accomplished with the following command: <code>\crescTextCresc</code>.
+ </para>
+ <para>
+ After changing to this style of ''crescendo'', you can revert to the standard < style with the following command: <code>\crescHairpin</code>.
+ </para>
+ <para>
+ The <code>\dimTextDim</code> and <code>\dimHairpin</code> commands do the same for a ''diminuendo''.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting-Polyphonic_Sections_of_Homophonic_Music">
+ <title>Polyphonic Sections of Homophonic Music</title>
+ <para>
+ Sometimes, especially in piano music, a passage of some measures will require polyphonic (multi-Voice) notation in LilyPond, even though most of the music does not. In this case, you would use the following format:
+ [pre]<<
+ {
+ % upper voice notes go here
+ } \\
+ {
+ % lower voice notes go here
+ }
+ >>[/pre]
+ This is used a few times in both hands in the example score file.
+ </para>
+ <para>
+ When writing these sections in "relative" entry mode, it is a good idea to use the "octave-check" mechanism, at least at the beginning of the lower voice. This is because, when judging the relative starting pitch of the first note of the lower voice, LilyPond judges from the last note of the upper voice - ''not'' the last note before the polyphonic section began.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Inputting-Octave_Change_Spanners">
+ <title>Octave-Change Spanners ("8ve" Signs, "Ottava Brackets")</title>
+ <para>
+ Musical Definition:
+ In order to most conveniently notate over large ranges, composers and editors sometimes use text spanners to indicate that a passage should be played one or two octaves higher or lower than written. This allows the notes to stay mostly within the staff lines, thereby decreasing the number of ledger lines required.
+ </para>
+ <para>
+ LilyPond Notation:
+ The <code>\ottava</code> command is used to notate all five states of transposition:
+ <itemizedlist>
+ <listitem><para>15va (play two octaves higher than written) is engaged with <code>\ottava #2</code></para></listitem>
+ <listitem><para>8va (play one octave higher than written) is engaged with <code>\ottava #1</code></para></listitem>
+ <listitem><para>''loco'' (play in the octave written) is engaged with <code>\ottava #0</code>, which also cancels another sign.</para></listitem>
+ <listitem><para>8vb (play one octave lower than written) is engaged with <code>\ottava #-1</code></para></listitem>
+ <listitem><para>15vb (play two octaves lower than written) is engaged with <code>\ottava #-2</code></para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ </section> <!-- Ends "Inputting" Section --> <!-- LilyPond-Piano-Inputting- -->
+
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Troubleshooting_Errors">
+ <title>Troubleshooting Errors</title>
+ <para>
+ It can be difficult to troubleshoot inputting errors, especially when you find them days or weeks after originally inputting that section of a score. The best way to fix errors is to input scores in a way that doesn't allow them in the first place. As they say, "an ounce of prevention is worth a pound of cure," which means "if you input your LilyPond files carefully, then you will encounter fewer problems." Such practices as proper spacing, and regular use of the octave- and bar-check features will deal with many common problems.
+ </para>
+ <para>
+ However, when searching for an error in your score, Frescobaldi does offer some features to help you find it:
+ <itemizedlist>
+ <listitem><para>If you have written something in the text-input window that is obviously incorrect, then Frescobaldi will sometimes catch your mistake and underline and highlight the erroneous code in red. This is most useful for catching typographical errors ("typos").</para></listitem>
+ <listitem><para>If LilyPond encounters a processing error, it will show up in the "LilyPond Log" window below the text-input window. You can click on the blue, underlined text to move the text-selection caret to the error.</para></listitem>
+ <listitem><para>If you can see an error in the PDF preview, but you can't find it in the source file, you can click on the problematic note or object in the PDF preview, and Frescobaldi will automatically move the text-selection caret to that object.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Formatting">
+ <title>Formatting the Score (Piano Dynamics)</title>
+ <para>
+ Keyboard instruments use a unique notation when it comes to dynamics. Most instruments use only one staff per player, so the dynamics are, by convention, notated underneath that staff. Keyboard instruments usually use two staves (organs and complex piano music may use three). Because the dynamics are usually meant to apply to both staves, they are usually notated between the two staves. This is similar to notation beneath the upper staff, but in truth, piano dynamics tend to be placed in the middle between the staves - entering the dynamics as belonging to the upper staff, in LilyPond, will not produce that effect.
+ </para>
+ <para>
+ There is a way to notate dynamics between two staves in LilyPond, and it involves a little bit of thought to get it right. It also requires the addition of a significant number of commands, and the creation of a new context.
+ </para>
+ <para>
+ This process looks difficult, and may seem daunting. It's not necessary to understand all of the commands in the "PianoDynamics" Context in order to use the context, so there is no need to worry!
+ </para>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Formatting-Preparing_the_PianoDynamics_Context">
+ <title>Preparing the "PianoDynamics" Context</title>
+ <para>
+ It is probably easier to add these commands before inputting most of the score, but there is no reason why this context cannot be added to any score at any time.
+ </para>
+ <para>
+ Follow these steps to create a "PianoDynamics" Context:
+ </para>
+ <procedure>
+ <step><para>Between the left and right staves of the PianoStaff, add "<code>\new PianoDynamics = "dynamics" \dynamics</code>". For the Schubert score, this looks like:
+ [pre] \new PianoStaff \with
+ {
+ instrumentName = "Piano"
+ }
+ <<
+ \new Staff = "right" \right
+ \new PianoDynamics = "dynamics" \dynamics
+ \new Staff = "left" { \clef bass \left }
+ >>[/pre]</para></step>
+ <step><para>To the layout section, add the following:
+ [pre]% Everything below here is for the piano dynamics.
+ % Define "PianoDynamics" context.
+ \context
+ {
+ \type "Engraver_group"
+ \name PianoDynamics
+ \alias Voice
+ \consists "Output_property_engraver"
+ \consists "Script_engraver"
+ \consists "New_dynamic_engraver"
+ \consists "Dynamic_align_engraver"
+ \consists "Text_engraver"
+ \consists "Skip_event_swallow_translator"
+ \consists "Axis_group_engraver"
+
+ \override DynamicLineSpanner #'Y-offset = #0
+ \override TextScript #'font-size = #2
+ \override TextScript #'font-shape = #'italic
+ \override VerticalAxisGroup #'minimum-Y-extent = #'(-1 . 1)
+ }
+
+ % Modify "PianoStaff" context to accept Dynamics context.
+ \context
+ {
+ \PianoStaff
+ \accepts PianoDynamics
+ }
+ % End of PianoDynamics code.[/pre]
+ This creates a "PianoDynamics" context, and modifies the "PianoStaff" context so that it will accept a "PianoDynamics" context.</para></step>
+ <step><para>Before the "\score" section, add a section called "dynamics," like this:[pre]dynamics =
+ {
+ % Dynamics go here.
+
+ }[/pre]
+ This is where you will input the dynamics.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Piano-Formatting-Inputting_the_Dynamics">
+ <title>Inputting the Dynamics</title>
+ <para>
+ Now you can input the dynamic markings. These are inputted with a special note called a "spacer," that uses the letter "s" rather than a note name. You can also use rests (both partial- and multi-measure, r and R), but dynamic markings cannot be assigned to them.
+ </para>
+ <para>
+ For example, if you want a ''piano'' marking on the first beat, and a ''diminuendo'' from the third to the fourth beat, you could write this: <code>s4\p r s\> s\!</code>, or this: <code>s2\p s4\> s\!</code>
+ </para>
+ <para>
+ That's all there is to it! Think of the dynamics part as an invisible, pitch-free line between the two staves, for the sole purpose of dynamics (and other expression markings).
+ </para>
+ </section>
+ </section> <!-- Ends "Formatting the Score (Piano Dynamics)" Section --> <!-- LilyPond-Piano-Formatting- -->
+
+</section>
diff --git a/en-US/LilyPond/LilyPond-syntax.xml b/en-US/LilyPond/LilyPond-syntax.xml
new file mode 100644
index 0000000..aa3f55c
--- /dev/null
+++ b/en-US/LilyPond/LilyPond-syntax.xml
@@ -0,0 +1,305 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<section id="sect-Musicians_Guide-LilyPond-Syntax">
+ <title>LilyPond Basics</title>
+ <para>
+ !! Somewhere in here, I have to mention bar- and octave-check devices !!
+ </para>
+ <para>
+ At its heart, LilyPond's syntax is designed to offer the most flexibility through the most diverse musical conditions. Over time, you will realize that features which seem too complex at first are really a very powerful and simple way to solve complex problems that commercial programs can't attempt.
+ </para>
+
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Letters_Are_Pitches">
+ <title>Letters Are Pitches</title>
+ <para>
+ One letter is all that's required to create a note in LilyPond. There are additional symbols and letters that are added to indicate further details, like the register, and whether the note is "sharp" or "flat."
+ </para>
+ <para>
+ Although it can be changed, the default (and recommended) way to indicate "sharp" or "flat" is by using Dutch note-names: "-is" to indicate a sharp, and "-es" to indicate a flat. For example, the following command would create b-double-flat, b-flat, b, b-sharp, and b-double-sharp: [pre]beses bes b bis bisis[/pre] Getting used to these names happens quickly, and they take less time to input than the English alternative. Furthermore, with these names, it becomes possible to sing note-names when you are ear training!
+ </para>
+ <para>
+ Pitch can be entered either absolutely, or relative to the preceding notes. Usually (for music without frequent large leaps) it is more convenient to use the "relative" mode. The symbols , and ' (comma and apostrophe) are used to indicate register.
+ </para>
+ <para>
+ When entering pitches absolutely, the register is indicated mostly as in the [http://en.wikipedia.org/wiki/Helmholtz_pitch_notation Helmholtz system]: octaves begin on the pitch "C," and end eleven tones higher on the pitch "B." The octave below "middle C" (octave 3 in [http://en.wikipedia.org/wiki/Scientific_pitch_notation Scientific Pitch Notation]) has no commas or apostrophes. The octave starting on "middle C" (octave 4) has one apostrophe; the octave above that (octave 5) has two apostrophes, and so on. Octave 2 (starting two octaves below "middle C") has one comma, the octave below that has two commas, and so on. It is usually not necessary to understand how to use this in LilyPond, or to be able to use it quickly, because most scores will use "relative mode."
+ </para>
+ <para>
+ When entering pitches relative to the previous one, the register is still indicated with commas or apostrophes, but usually none are needed. When using this input mode, the octave of each note is guessed based on the octave of the previous note. Think of it this way: the next note will always be placed so it produces the smaller interval. For example, after a C, an E could be placed as a major third, a minor sixth, a major tenth, a minor thirteenth, and so on. In relative mode, LilyPond will always choose the "major third" option. If you wanted LilyPond to notate the E so that it's a minor sixth, you would tell LilyPond with a comma appended: <code>c e,</code> so that LilyPond knows what you want. It's the same case if you were to input <code>c aes</code> (meaning "C then A-flat"): the A-flat will be notated so that it is a major third from the C; if you wanted LilyPond to notate it so that the A-flat is a minor sixth higher than the C, you would need to append an a
postrophe: <code>c aes'</code>
+ </para>
+ <para>
+ The only possible ambiguity with this is with a tritone. LilyPond solves this by not recognizing "tritones," per se, and thinking of them as "augmented fourth" or "diminished fifth." Unless instructed otherwise (with a comma or apostrophe), LilyPond will always notate the interval as an augmented fourth.
+ </para>
+ <para>
+ You must always indicate a sharp or flat, even if it is already in a key signature. This ultimately helps to reduce the number of errors.
+ </para>
+ <para>
+ Letters used to indicate pitch are always in lower-case.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Numbers_Are_Durations">
+ <title>Numbers Are Durations</title>
+ <para>
+ A number appended to a letter is understood by LilyPond to indicate that note's note-value. A ''whole note'' is indicated with a 1, and all other notes with a number representing the fraction of a whole note that they occupy: ''half notes'' are 2 (like "1/'''2''' note"); ''quarter notes'' are 4 (like "1/'''4''' note"); ''eighth notes'' are 8 (like "1/'''8''' note") and so on.
+ </para>
+ <para>
+ To add a "dot" to a note (thereby increasing its length by one half), you simply include a period after the number. For example, <code>e4.</code> means "dotted quarter note on E."
+ </para>
+ <para>
+ To add a "tie" from one note to the next (thereby continuing its duration across a measure-line), add a tilde ( ~ ) after the pitch and duration.
+ </para>
+ <para>
+ After indicating a duration, it is assumed that all subsequent notes have the same duration, until indicated otherwise.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Articulations">
+ <title>Articulations</title>
+ <para>
+ Many different symbols are used to tell LilyPond to add articulation signs to a note. They are all appended after the pitch and (if included) duration, and many have a position indicator, too.
+ </para>
+ <para>
+ A full list of articulation markings is available in the LilyPond manual, and Frescobaldi remembers most of them for you (they are stored in the left-side panel).
+ </para>
+ <para>
+ These are some of the most common articulation marks, which use a position indicator unless specified otherwise:
+ <itemizedlist>
+ <listitem><para>( to begin a slur (no position indicator)</para></listitem>
+ <listitem><para>) to end a slur (no position indicator)</para></listitem>
+ <listitem><para>~ to begin a tie (which needs no end; no position indicator)</para></listitem>
+ <listitem><para>. for a ''staccato'' mark</para></listitem>
+ <listitem><para>> for an ''accent''</para></listitem>
+ <listitem><para>- for a ''tenuto'' mark</para></listitem>
+ <listitem><para>^ for a ''marcato'' mark</para></listitem>
+ <listitem><para>_ for a ''portato'' mark (dot and line)</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ There are three position indicators:
+ <itemizedlist>
+ <listitem><para>- which means to put the articulation mark wherever LilyPond thinks it makes sense</para></listitem>
+ <listitem><para>_ which means to put the articulation mark ''below'' the note-head</para></listitem>
+ <listitem><para>^ which means to put the articulation mark ''above'' the note-head</para></listitem>
+ </itemizedlist>
+ These position indicators will sometimes result in notes like: <code>g4--</code>, <code>g4__</code>, and <code>g4^^</code>, but although this may look incorrect, it is perfectly acceptable.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Simultaneity">
+ <title>Simultaneity</title>
+ <para>
+ Simply put, anything enclosed inside << and >> is considered by LilyPond to happen simultaneously. This can be used in any context (and any Context - see above/below). It is possible to tell LilyPond that you want two notes to happen at the same time in the same voice (yielding a chord), at the same time on the same staff (yielding polyphony), and so on. Moreover, any score with multiple staves will use << and >> to tell LilyPond that the parts should begin at the same time, and creative use of << and >> is one of the keys to advanced notation.
+ </para>
+ <para>
+ It is not important to understand simultaneity at first. By observing how Frescobaldi creates scores for you, and how examples on the internet take advantage of these symbols, you will eventually understand how to use them.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Chords">
+ <title>Chords</title>
+ <para>
+ Making use of the << and >> idea to indicate simultaneity, if a note has multiple pitches indicated between > and < then LilyPond assumes that they are in a chord together. Notating a single chord with single > < brackets has two advantages: firstly, it is easier to see that they are a chord and not something more complex; secondly, it allows you to enter information more clearly.
+ </para>
+ <para>
+ Consider the following examples, which should produce equivalent output:
+ [pre]<<g'4->-5 b d>>[/pre]
+ [pre]<g' b d>4->-5[/pre]
+ With the first example, it is more difficult to see the chord notes, the duration, and what the "5" means. With the second example, it is easy to see that the chord notes are a G, a B, and a D, that they have quarter-note duration, and that the "5" is actually a fingering indication.
+ </para>
+ <para>
+ There is another advantage to using < and > for notation of simple chords: they preserve logical continuity in "relative" mode. The following note will always be notated as relative to the lowest note in the chord, regardless of how many octaves the chord covers. This is not true with << and >>, where where following notes will be notated as relative to the last note between the << and >> .
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Commands">
+ <title>Commands</title>
+ <para>
+ There are a wide variety of commands available in LilyPond, some of them quite simple, and other quite complex. They all begin with a backslash, followed by the name of the command, and subsequent "arguments" that give the command further information about what you want it to do. Just like using a letter to indicate a note, commands are simply another way for you to tell LilyPond how you want your score to be rendered.
+ </para>
+ <para>
+ For example, <code>\time 2/4</code> and <code>\clef bass</code> are two commands that you are likely to use quite often. They happen to do precisely what it seems like they should: ''time'' changes the time signature and metre, and ''clef'' changes the clef. they belong to differen contexts (''time'' applies for the whole Score, but ''clef'' for only one Staff).
+ </para>
+ <para>
+ It can take some time to remember even these basic commands and the way you should format their input, and this is where Frescobaldi's built-in documentation viewer can help out. All of the official LilyPond documentation is made available in Frescobaldi, which makes it easy for you to view the documentation and make changes to your score in the same window of the same application.
+ </para>
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Commands-Customization">
+ <title>Customization</title>
+ <para>
+ It is rarely necessary to customize LilyPond's output in a way that is very specific, and not allowed for in the standard LilyPond syntax. As a beginner, this can happen quite often when you are trying to exactly emulate the look of a pre-existing score. Remember that LilyPond provides a content-focussed way to express music, and that it will usually produce meaningful output without advanced interference. If in doubt about whether a customization is really necessary, ask yourself this: will it change the music that is played from the score?
+ </para>
+ <para>
+ If you really must customize some setting, then keep in mind these two points:
+ <orderedlist>
+ <listitem><para>Tinkering with LilyPond can become as complex as you want.</para></listitem>
+ <listitem><para>Ultimately all tinkering takes the form of commands.</para></listitem>
+ </orderedlist>
+ </para>
+ <para>
+ Searching the internet for LilyPond tips and tricks can be a life-saver, but it can also lead to needlessly complex solutions. Sometimes this is the result of poor solutions being posted on the internet, but more often it is the result of LilyPond's ongoing development, which makes better solutions available regularly. For this reason, it is recommended to search the official LilyPond documentation first, then the "LilyPond Snippet Repository" (LSR - link here), and then Google.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Commands-Contexts">
+ <title>Contexts</title>
+ <para>
+ Another aspect of LilyPond that often confuses beginners is the idea of contexts. It is an essential concept for modifying default behaviour. Like everything in LilyPond, it makes perfect sense: "context" means "context." The three primary contexts are "Voice," "Staff," and "Score." Everything that happens in a score happens in a context - it's just that simple - everything happens in a context! Everything that happens in a score happens in Score context, everything that happens on a staff happens in a Staff context, and everything that happens in a voice happens in a Voice context.
+ </para>
+ <para>
+ To help clear things up a little, here are three examples:
+ <orderedlist>
+ <listitem><para>Where does the title of a composition belong?
+ <itemizedlist>
+ <listitem><para>Does it belong on the score? Yes, so it belongs in the Score context.</para></listitem>
+ <listitem><para>Does it belong on a staff? No, so it doesn't belong in a Staff context.</para></listitem>
+ <listitem><para>Does it belong in a voice? No, since it would have to be on a staff to be in a voice.</para></listitem>
+ </itemizedlist>
+ The composition's title doesn't belong on a staff or in a voice, but it does belong on the score, so we say that it happens in the Score context.</para></listitem>
+ <listitem><para>Where does a clef belong?
+ <itemizedlist>
+ <listitem><para>Does it belong on the score? Yes, because it is a part of notation.</para></listitem>
+ <listitem><para>Does it belong on a staff? Yes, because it wouldn't make sense to have a clef off a staff.</para></listitem>
+ <listitem><para>Does it belong in a voice? No, because it's not related to a specific "line" or voice.</para></listitem>
+ </itemizedlist>
+ Clefs usually belong on the staff, at the beginning of every line, so we say that they happen in a Staff context.</para></listitem>
+ <listitem><para>Where does a note-head belong?
+ <itemizedlist>
+ <listitem><para>Does it belong on the score? Yes, because it is a part of notation.</para></listitem>
+ <listitem><para>Does it belong on a staff? Yes - even if it's on a ledger line, note-heads are meaningless unless they're on a staff.</para></listitem>
+ <listitem><para>Does it belong in a voice? Yes, because one particular musical line is indicated primarily with note-heads.</para></listitem>
+ </itemizedlist>
+ Note-heads belong to a particular voice, so we say they happen in a Voice context.</para></listitem>
+ </orderedlist>
+ </para>
+ <para>
+ To help further clarify, consider the following:
+ </para>
+ <para>
+ As in the real world, objects in LilyPond can potentially happen in any context...
+ <itemizedlist>
+ <listitem><para>(like a doorknob on a door)</para></listitem>
+ <listitem><para>(like a bus driver sitting in a bus' drivers' seat)</para></listitem>
+ <listitem><para>(like a person buying groceries at a supermarket)</para></listitem>
+ <listitem><para>(like a flat-sign next to a note-head)</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ ... some contexts are unusual, but make sense...
+ <itemizedlist>
+ <listitem><para>(like a doorknob on a wall, if the wall is designed to look like a door)</para></listitem>
+ <listitem><para>(like a bus driver sitting in a passenger seat, if they are going to the garage)</para></listitem>
+ <listitem><para>(like a person buying groceries from a corner store, if the supermarkets are closed)</para></listitem>
+ <listitem><para>(like a flat sign in a paragraph of text, if that paragraph describes what flat signs do)</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ ... and some contexts do not make sense, but can still happen...
+ <itemizedlist>
+ <listitem><para>(like a doorknob on a television)</para></listitem>
+ <listitem><para>(like a bus driver serving patrons at a restaurant)</para></listitem>
+ <listitem><para>(like a person buying groceries at a governmental office)</para></listitem>
+ <listitem><para>(like a flat sign in the top corner of a score, where the page number should be)</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Because LilyPond's designers wisely decided that they could not conceive of all the possible uses for something, they allowed any plug-in/engraver/tool to be used in any context(?? I think ??). Furthermore, they decided that a Context should be allowed to happen within another Context, which makes sense - a Voice context only makes sense if it appears on a Staff, and a Staff only makes sense if it appears in a Score.
+ </para>
+ <para>
+ So, when trying to sort out the context in which something should apply, ask yourself exactly that: "In what context does this apply?" Beams and flags happen in one voice, accidentals apply to a whole staff, and tempo markings apply to the whole score. Although it may take some careful thought to get used to the idea, contexts ultimately make perfect sense.
+ </para>
+ </section>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Syntax-Source_Files">
+ <title>Source Files and Their Formatting</title>
+ <para>
+ Source files are the text files prepared with instructions telling LilyPond the content of the score you want it to create. They are so called because these files are the "source" of what you wish to create. As with programming languages, the text inside these files is often referred to as "source code." It sounds scary to think that you must edit code in order to use LilyPond, but "code" just means that it isn't normal English (or insert-language-here).
+ </para>
+ <para>
+ The particular formatting (the placement of tabs, spaces, and newlines) is not determined by LilyPond, but by individual users. This can be a headache when you encounter somebody else's formatting, but it is one of the keys to LilyPond's flexibility. This Guide uses a very specific style of formatting, but it should be understood that this is simply the style of one user, affected by their experiences, and the tasks they usually perform in LilyPond.
+ </para>
+ <para>
+ You will eventually develop your own style, better-suited to the kinds of tasks that you accomplish. When you do this, there is only one rule to keep in mind: be consistent within source files. When source files are programmed in a consistent way, it means that anybody who wants to use those files (like yourself, in the future) will easily be able to determine how they are organized.
+ </para>
+ <section id="sect-Musicians_Guide-">
+ <title>Organizing Files, and Where to Put the Notes</title>
+ <para>
+ LilyPond files are constructed as a series of commands. For better or worse, LilyPond's interpreter allows a great deal of flexibility when it comes to source file setup. This can lead to confusion about where things should be done, especially when using automated score-setup tools like Frescobaldi.
+ </para>
+ <para>
+ The generic structure of a LilyPond source file is this:
+ [pre]\version "whatever_version"
+
+ \header { things like title, composer, and so on }
+
+ \score
+ {
+ \new Staff
+ {
+ notes can go here
+ }
+
+ \layout
+ {
+ }
+
+ and so on
+ }[/pre]
+ </para>
+ <para>
+ Confusion arises here: for maximum flexibility, LilyPond allows source files to create its own commands. On hearing this, you may think, "Okay that's it - I don't need advanced commands or any of this stuff, so I'm packing it in and just using Finale!" There's no need to do that just yet - commands are easy! Think of commands - whether you wrote them or they were included with LilyPond - as a means of text-substition.
+ </para>
+ <para>
+ It works like this:
+ </para>
+ <procedure>
+ <step><para>You "define" (create) a command with the form <code>commandName = { lots of commands }</code></para></step>
+ <step><para>You can then use the command anywhere below that, as many times as you want, by writing <code>\commandName</code> in your source file. When LilyPond processes that portion of text, it will instead see whatever you wrote in the definition.</para></step>
+ </procedure>
+ <para>
+ It's as easy as 1-2!
+ </para>
+ <para>
+ Frescobaldi (along with most LilyPond users) take advantage of this functionality to provide well-organized, easy-to-use source files.
+ </para>
+ <para>
+ Here is a good template source file, that might be created for you by Frescobaldi:
+ [pre]\version "2.12.2"
+
+ \header
+ {
+ title = "Example"
+ }
+
+ violin = \relative c''
+ {
+ \key c \major
+ \time 4/4
+ % Music follows here.
+ }
+
+ \score
+ {
+ \new Staff \with
+ {
+ instrumentName = "Violin"
+ }
+ \violin
+ \layout { }
+ }[/pre]
+ </para>
+ <para>
+ This source file makes use of many commands, and even defines "violin" for its own use. It may not be easy to see from this simple example, but keeping your notes separated from the formatting of a complex ''\score'' section will greatly improve the readability of both sections. Furthermore, you will easily be able to search through thousands of lines of source file to find the section that you want.
+ </para>
+ <para>
+ So where do the notes go? In this template, they should go in the "violin" section. Frescobaldi usually marks this off with a friendly comment, stating "% Music follows here." That's exactly what it means: most of your time will be spent working with what follows there.
+ </para>
+ <para>
+ As a final note, we caution against removing the "layout" section of the "score" section. Removing the "layout" section would cause LilyPond not to create a score as output.
+ </para>
+ </section>
+ </section>
+
+</section>
diff --git a/en-US/LilyPond/LilyPond.xml b/en-US/LilyPond/LilyPond.xml
new file mode 100644
index 0000000..c7bad7c
--- /dev/null
+++ b/en-US/LilyPond/LilyPond.xml
@@ -0,0 +1,74 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<chapter id="chap-Musicians_Guide-LilyPond">
+ <title>LilyPond</title>
+ <para>
+ LilyPond is a notation engraving program, with a focus on creating a visually appealing product. LilyPond is text-based, and allows you to focus on the (semantic?) content of your musical scores, rather than on their visual appearance. Conventional commercial notation engraving programs allow users to edit the score visually. While this approach has its benefits, especially because it's very easy to see exactly what the printed score will look like, it also has disadvantages - chief among these is the fact that users of those programs are constantly worrying about what their score looks like.
+ </para>
+ <para>
+ This is where LilyPond comes in - users don't need to worry about how their score will work, because they know that the expertly-crafted methods of LilyPond will automatically configure the objects on the score so that they look good, and are easy to read. LilyPond's users focus on ''what'' needs to be displayed, rather than on ''how'' it is going to be displayed.
+ </para>
+ <para>
+ As with any particular approach, the LilyPond approach is not for everybody. However, once you have become accustomed to working with the software, and once you have learned methods to help deal with problems and organize your scores' source-files, you will probably realize that LilyPond is both much faster, and much more flexible, than traditional, commercially-available music engraving programs.
+ </para>
+ <para>
+ LilyPond offers many other features, too. Some of these features include:
+ <itemizedlist>
+ <listitem><para>Putting scores into LaTeX or HTML documents.</para></listitem>
+ <listitem><para>Putting scores into OpenOffice.org documents, with the <code>ooolilypond</code> program.</para></listitem>
+ <listitem><para>Being compatible with all major operating systems.</para></listitem>
+ <listitem><para>Managing parts and full scores for large compositions.</para></listitem>
+ <listitem><para>Allowing new musical symbols with the Scheme programming language.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ It is the goal of this guide to help users more quickly overcome the initial learning handicap incurred because of the text-based approach. Making use of tools such as the Frescobaldi text-editor will help to increase productivity, to make trouble-shooting easier, and to ease the memory burden associated with the text-based approach.
+ </para>
+
+ <section id="sect-Musicians_Guide-LilyPond-How_LilyPond_Works">
+ <title>How LilyPond Works</title>
+ <para>
+ LilyPond itself can be thought of as a highly-skilled automobile mechanic with a well-equipped toolbox. Regardless of the problem presented to the mechanic, they will automatically know which tools to use. Some of their tools are available elsewhere, and some are quite basic, but it is not the tools themselves that gives the mechanic their power, but rather the ways in which the mechanic uses the tools. Similarly, LilyPond is run as a single program (as you would consult a single mechanic), but it employs a multitude of tools - some available elsewhere, but others specialized, so that the resulting output is useful to us in some way.
+ </para>
+ <para>
+ In order to create meaningful output with LilyPond, we need to provide it meaningful instructions, and this we do in text files with the *.ly extension. These instructions will tell LilyPond which tools to use, when, and with what settings. Sometimes, we will need to change LilyPond's default settings; this is intimidating at first, but really we are just providing more specific instructions for what we want LilyPond to do. To return to the mechanic metaphor: not only would you be able to ask for repairs, but you will be able to ask for specific components or specific methods of installation; once you realize the power, flexibility, and easiness that is changing LilyPond settings, you will have truly unleashed its power.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-The_LilyPond_Approach">
+ <title>The LilyPond Approach</title>
+ <para>
+ For an extensive explanation of the following section, please see [http://www.lilypond.org/about/automated-engraving/ the official LilyPond documentation], from where this was sourced.
+ </para>
+ <para>
+ ??
+ LilyPond works by separating the tasks of what to put, and where to put it. Each aspect of an object's positioning is controlled by a specific plug-in. Although software using "plug-ins" often results in messy and uncooperative plug-ins, such is not the case with LilyPond. You can think of the plug-ins as tools. LilyPond knows how and when to use each tool; if it doesn't know enough about a tool, then it isn't used, so there's no concern about half-baked plug-ins that work for one person in one situation, but for nothing else.
+ ??
+ </para>
+ <para>
+ Before LilyPond places an object, it first considers many different possibilities for the specific alignment and layout of that object. Then it evaluates the possibilities according to aesthetic criteria set out to reflect those used in hand-engraved notation. After assigning each possibility a score representing how closely it resembles to the aesthetic ideal, LilyPond then chooses the least problematic possibility.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-LilyPond-Installation">
+ <title>Installation</title>
+ <procedure>
+ <step><para>Run <code>sudo -c 'yum install lilypond'</code> or use PackageKit or KPackageKit to install the "lilypond" package.</para></step>
+ <step><para>Review the dependencies; it will want to install a lot of things called lilypond-*-fonts</para></step>
+ <step><para>LilyPond can be run from the command-line, as 'lilypond'</para></step>
+ </procedure>
+ <para>
+ It is recommended that you use the "Frescobaldi" text editor, which is designed specifically for use with LilyPond. It has many features that help to enhance productivity when editing LilyPond files, and which greatly speed up the learning process. Please see this section of the Musicians' Guide for help installing Frescobaldi.
+ </para>
+ </section>
+
+ <xi:include href="LilyPond-syntax.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="LilyPond-counterpoint.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="LilyPond-piano.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="LilyPond-orchestra.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+</chapter>
diff --git a/en-US/Musicians_Guide.xml b/en-US/Musicians_Guide.xml
index f320c42..9953082 100644
--- a/en-US/Musicians_Guide.xml
+++ b/en-US/Musicians_Guide.xml
@@ -14,12 +14,25 @@
<xi:include href="Real_Time_and_Low_Latency.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<!-- Audio and Music Software -->
- <xi:include href="Audacity.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="Digital_Audio_Workstations.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="Ardour.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="Qtractor.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="Rosegarden.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="FluidSynth.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <!-- Audio Editor -->
+ <xi:include href="Audacity.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <!-- Digital Audio Workstations (DAWs) -->
+ <xi:include href="Digital_Audio_Workstations.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Ardour.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Qtractor.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Rosegarden.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <!-- Synthesizers -->
+ <xi:include href="FluidSynth.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="SuperCollider/SuperCollider.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <!-- Typesetting -->
+ <xi:include href="LilyPond/LilyPond.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Frescobaldi.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <!-- Aural Skills Training -->
+ <xi:include href="Solfege.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<!-- End Chapters -->
<xi:include href="Revision_History.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
diff --git a/en-US/Solfege.xml b/en-US/Solfege.xml
new file mode 100644
index 0000000..c0f4ce7
--- /dev/null
+++ b/en-US/Solfege.xml
@@ -0,0 +1,490 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<chapter id="chap-Musicians_Guide-Solfege">
+ <title>GNU Solfege</title>
+
+ <section id="sect-Musicians_Guide-Solfege-Requirements_and_Installation">
+ <title>Requirements and Installation</title>
+
+ <section id="sect-Musicians_Guide-Hardware_and_Software_Requirements">
+ <title>Hardware and Software Requirements</title>
+ <para>
+ It is assumed that, prior to using GNU Solfege, users have already correctly configured their audio equipment.
+ </para>
+ <para>
+ In addition, the <code>timidity++</code> package is required by Solfege, which requires the installation of a large (approximately 140 MB) SoundFont library. This library is shared with the <code>FluidSynth</code> application, which has its own section in this Guide, and is used by several other software packages. <code>timidity++</code> also requires the installation of the JACK Audio Connection Kit. If you have installed the Planet CCRMA at Home repository, and have not yet followed the instructions to correctly install and configure its version of JACK, then it is recommended that you do so before installing GNU Solfege. Instructions can be found [[User:Crantila/FSC/Sound_Servers#Installing_JACK|here]].
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Other_Requirements">
+ <title>Other Requirements</title>
+ <para>
+ Solfege requires knowledge of Western musical notation, and basic music theory terms and concepts.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Install">
+ <title>Required Installation</title>
+ <para>
+ Please review the "Requirements" section above, before installation.
+ </para>
+ <para>
+ Use PackageKit, KPackageKit to install the <code>solfege</code> package, or run [pre]su -c 'yum install solfege'[/pre] in a terminal.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Install_Csound">
+ <title>Optional Installation: Csound</title>
+ <para>
+ Csound is a sound-synthesis program, similar to SuperCollider. It is older, quite well-developed, and has a broader range of features.
+ </para>
+ <para>
+ To install Csound, first close Solfege, then use PackageKit or KPackageKit to install the "csound" package, or run <code>su -c 'yum instal csound'</code> in a terminal. When Solfege is restarted, you will be able to use the "Intonation" exercises.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Install_MMA">
+ <title>Optionsl Installation: MMA</title>
+ <para>
+ MMA stands for "Musical MIDI Accompaniment," and it is not available for Fedora in a pre-packaged format. The software can be found on the internet from [http://www.mellowood.ca/mma/ here], where you can download the source code and compile it if desired. MMA is only used by some of the harmonic dictation questions, so its installation is not required.
+ </para>
+ </section>
+ </section> <!-- Ends "Requirements and Installation" Section -->
+
+ <section id="sect-Musicians_Guide-Solfege-Configuration">
+ <title>Configuration</title>
+ <para>
+ It is not necessary to configure Solfege. The simple first-time configuration will help to customize the application for your needs, but it is not required. The other configuration options are explained for your reference.
+ </para>
+ <para>
+ These configuration options are not required, but you may wish to change them. They are all available from the "Preferences" window, accesible through Solfege's main menu: 'File > Preferences'.
+ </para>
+ <section id="sect-Musicians_Guide-Solfege-Configuration-First_Time">
+ <title>When You Run Solfege for the First Time</title>
+ <para>
+ These steps allow Solfege to automatically customize some questions for you.
+ </para>
+ <procedure>
+ <step><para>Start Solfege.</para></step>
+ <step><para>From the menu, select 'File > Preferences'.</para></step>
+ <step><para>Select the "User" tab.</para></step>
+ <step><para>Input your vocal range, if you know it. Solfege uses this information to assign questions in a comfortable pitch range.</para></step>
+ <step><para>Input your biological gender in the "Sex" field. Solfege uses this information to assign questions in the correct octave.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Configuration-Instruments">
+ <title>"Instruments" Tab</title>
+ <para>
+ <itemizedlist>
+ <listitem><para>Tempo: Changes the speed at which examples are played.
+ <itemizedlist>
+ <listitem><para>Default: Applies to everything that isn't an "Arpeggio."</para></listitem>
+ <listitem><para>Arpeggio: Applies to arpeggios, which are, by default, played at three times the speed of the default tempo. This is standard practice.</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem><para>Preferred Instrument: This MIDI instrument will be used when playing examples.</para></listitem>
+ <listitem><para>Chord Instruments: For polyphonic voices, these MIDI instruments will be used for the highest, middle, and lowest voices above the bass voice (which takes the "preferred instrument.")</para></listitem>
+ <listitem><para>Percussion instruments:
+ <itemizedlist>
+ <listitem><para>Count in: This MIDI instrument will be used to give "count in" beats that precede musical examples involving rhythm.</para></listitem>
+ <listitem><para>Rhythm: This MIDI instrument will be used to dictate rhythm-only examples.</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Configuration-External_Programs">
+ <title>"External Programs" Tab</title>
+ <para>
+ Solfege uses external programs to perform many tasks. On this tab, you can provide the command to be used, as though being run from a terminal.
+ </para>
+ <para>
+ Converters:
+ <itemizedlist>
+ <listitem><para>MIDI to WAV</para></listitem>
+ <listitem><para>WAV to MP3</para></listitem>
+ <listitem><para>WAV to OGG</para></listitem>
+ <listitem><para>If you use %(in)s and %(out)s, Solfege will substitute the filename it wants inputted and outputted.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Audio File Players, each with "Test" buttons:
+ <itemizedlist>
+ <listitem><para>WAV</para></listitem>
+ <listitem><para>OGG</para></listitem>
+ <listitem><para>MP3</para></listitem>
+ <listitem><para>MIDI</para></listitem>
+ <listitem><para>Solfege will substitute %s with the name of the file to be played.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Miscellaneous:
+ <itemizedlist>
+ <listitem><para>CSound: Solfege uses CSound for intonation exercises. It is an optional component. See the "Optional Installation" section above.</para></listitem>
+ <listitem><para>MMA: Solfege uses MMA for certain harmonic dictation exercises. It is an optional component, and not available in Fedora through standard means. See the project's [http://www.mellowood.ca/mma/ home page] for details.</para></listitem>
+ <listitem><para>Lilypond-book: Solfege uses this for generating print-outs of ear training exercise progress. See the "Optional Installation" section above.</para></listitem>
+ <listitem><para>Latex: Solfege uses this for generating *.dvi format progress reports, rather than the default HTML format.</para></listitem>
+ <listitem><para>Latex: Solfege uses this for generating *.dvi format progress reports, rather than the default HTML format.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Configuration-Interface">
+ <title>Interface</title>
+ <para>
+ <itemizedlist>
+ <listitem><para>Resizeable main window: This allows users to resize the main Solfege window.</para></listitem>
+ <listitem><para>Select language</para></listitem>
+ <listitem><para>Identify tone keyboard accelerators: In exercises requiring the input of particular pitches, this will allow a conventional keyboard to be used as a MIDI keyboard - letters on the keyboard will be associated with particular pitches.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Configuration-Practise">
+ <title>Practise</title>
+ <para>
+ These options apply to exercises done in "Practise" mode.
+ <itemizedlist>
+ <listitem><para>"Not allow new question before the old is solved": Solfege will not provide a new question until you have solved the current question.</para></listitem>
+ <listitem><para>"Repeat question if the answer was wrong": Solfege will repeat a question if you provide an incorrect answer.</para></listitem>
+ <listitem><para>"Expert mode": Solfege will provide advanced configuration options for individual exercises.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Configuration-Sound_Setup">
+ <title>Sound Setup</title>
+ <para>
+ <itemizedlist>
+ <listitem><para>"No sound": This mode is used for testing and debugging Solfege.</para></listitem>
+ <listitem><para>"Use device": This mode lets you specify which audio interface Solfege will use.</para></listitem>
+ <listitem><para>"User external MIDI player": This mode lets you choose a MIDI synthesizer.</para></listitem>
+ <listitem><para>The button, "Test": allows you to ensure that you've correctly configured Solfege.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ </section> <!-- Ends "Configuration" Section --> <!-- Solfege-Configuration- -->
+ <section id="sect-Musicians_Guide-Solfege-Training">
+ <title>How to Train Yourself</title>
+ <para>
+ There are three kinds of exercises available in Solfege:
+ <itemizedlist>
+ <listitem><para>"Listen-and-identify" exercises will play some sort of musical structure, and ask you to identify, classify, or label it according to widely-used conventions.</para></listitem>
+ <listitem><para>"Identify" exercises will show you some sort of musical structure (usually in Western classical notation), and ask you to identify, classify, or label it according to widely-used conventions.</para></listitem>
+ <listitem><para>"Sing" exercises will provide a specific musical structure, sometimes partially-completed, and ask you to sing the completion of the structure.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Unlike many commercially-available aural skills computer applications, Solfege often relies on the user to know whether they performed the task correctly - and how correctly. This is especially true of the "Sing"-type exercises, since Solfege lacks the capability to receive sung input from the user. This requires at least two things to be kept in mind: firstly, that it is to your own benefit to honestly tell Solfege when you correctly and incorrectly provide a solution, since this helps Solfege to focus on your weaknesses, and to more accurately track your progress; secondly, there are many degrees of correctness when it comes to music, and harmonic and melodic dictation are particularly prone to these forms of partial correctness.
+ </para>
+ <para>
+ When you encounter a rough spot with your aural skills development, remember that it takes a significant amount of time and effort to build your musical sensibility. It is easier for some people than for others, and most people will have an easier time with some exercises than with others. Although the prevailing cultural thought about musical sensibility (and aural skillls) still suggests that an individual either posesses musical ability or cannot acquire it, recent research has suggested that any hearing person with enough determination, dedication, and the right instruction can develop their musical sensibility and aural skills to a very high level.(!! cite?? !!)
+ </para>
+ <para>
+ With that in mind, the following sections aim to help you incorporate Solfege as part of a complete aural skills development program.
+ </para>
+ <section id="sect-Musicians_Guide-Solfege-Training-Aural_Skilla_and_Musical_Sensibility">
+ <title>Defining "Aural Skills" and "Musical Sensibility"</title>
+ <para>
+ When somebody decides to receive musical training, what they are really doing is developing skills and acquiring stylistic knowledge required for participation in a particular kind of music. There are many different kinds of training, and the time spent in a classroom is not as important to musical development as time spent elsewhere, taking part in real, musical situations. Many different kinds of skills are useful for musicians, depending on the kind of music in which they intend to participate. A folk singer who plays guitar might wish to memorize the chord progressions, melodies, and words for thousands of different songs. An oboe player in an orchestra might wish to make their own reeds from cane tree bark. Most musicians need to be able to listen to music and perceive certain structures that other musicians use to describe their work. These structures are explained by "music theory," and the skill set used to hear these things in music is called "aural skills
." Musicians train their aural skills by a set of procedures known as "ear training," or "aural skills training."
+ </para>
+ <para>
+ Musical sensibility is developed when aural skills are used to help a musician gain an understanding of how and why their music (and other people's music) works and sounds the way it does. This understanding is key to having a sense of the procedures and conventions that an audience will expect of a performer, and therefore to the performer's ability to produce aesthetically pleasing music.
+ </para>
+ <para>
+ Having a well-developed musical sensibility and set of aural skills are both important aspects of being a musician, but they are by no means the only aspects. More than anything, a musician (or an aspiring musician) should be talking and listening to other musicians.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Training-Exercise_Types">
+ <title>Exercise Types</title>
+ <para>
+ Solfege's exercises are arranged in six broad categories:
+ <itemizedlist>
+ <listitem><para>Intervals, which tests your ability to perceive and identify melodic and harmonic intervals.</para></listitem>
+ <listitem><para>Rhythm, which tests your ability to perceive and notate rhythms played with a single pitch, and to perform such a rhythm by means of tapping on the keyboard.</para></listitem>
+ <listitem><para>Theory, which tests your ability to name written intervals and scales, and to correctly use solfa syllables.</para></listitem>
+ <listitem><para>Chords, which tests your ability to perceive and identify chords built from various intervals, played at various pitch levels, and to sing such a chord.</para></listitem>
+ <listitem><para>Scales, which tests your ability to perceive and identify scales and their modes.</para></listitem>
+ <listitem><para>Miscellaneous, which includes a variety of exercises, including:
+ <itemizedlist>
+ <listitem><para>Intonation, which tests your ability to perceive and identify whether a second pitch is lower or higher than it should be.</para></listitem>
+ <listitem><para>Dictation, which tests your ability to perceive and notate melodies.</para></listitem>
+ <listitem><para>Identify Tone, which tests your ability to use [http://en.wikipedia.org/wiki/Relative_pitch relative pitch].</para></listitem>
+ <listitem><para>Sing Twelve Random Tones, which tests many skills.</para></listitem>
+ <listitem><para>Beats per Minute, which tests your ability to determine a tempo.</para></listitem>
+ <listitem><para>Harmonic Progressions, which tests your ability to perceive and apply Roman numeral chord symbols for a series of chords played together.</para></listitem>
+ <listitem><para>Hear Tones, which helps you to train for relative pitch.</para></listitem>
+ <listitem><para>Cadences, which tests your ability to perceive and apply Roman numeral chord symbols for two chords played together.</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ All of these exercises require the use of your aural skills outside an actual musical situation. This may seem fruitless, but it has long been recognized as an important part of the eventual ability to hear them within a musical context. Neither ability will suddenly appear; it will take dedicated practice.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Training-Making_an_Aural_Skills_Program">
+ <title>Making an Aural Skills Program</title>
+ <para>
+ Aural skills training - like eating - requires a regular, daily commitment of various kinds of input. As far as food is concerned, you should eat at least three meals a day, with a large portion of fruits and vegetables, and a good balance of meats and alternatives, grains, and other kinds of foods. Ear training also requires diverse inputs at various times throughout the day.
+ </para>
+ <para>
+ There is no solution that will work for everybody. You will need to choose and modify the time of day, number and length of sessions, and content to suit your needs. The following suggestion can be considered a starting point.
+ <itemizedlist>
+ <listitem><para>Training for 30 minutes daily, in three 10-minute segments.</para></listitem>
+ <listitem><para>Segment 1
+ <itemizedlist>
+ <listitem><para>When you wake up, before breakfast.</para></listitem>
+ <listitem><para>Warm up your voice and body (good activity anyway - ''not'' part of the ten minutes!)</para></listitem>
+ <listitem><para>Sing and perfect some excerpts from a book designed for sight-singing.</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem><para>Segment 2
+ <itemizedlist>
+ <listitem><para>After lunch, before getting back to work.</para></listitem>
+ <listitem><para>Listen to some music, then try to transcribe it.</para></listitem>
+ <listitem><para>To make the task more manageable, take a small portion of music, and focus on one aspect: melody, harmony, or rhythm.</para></listitem>
+ <listitem><para>You can test correctness either by using a piano (or fixed pitch reference), or comparing with a published score, if available.</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem><para>Segment 3
+ <itemizedlist>
+ <listitem><para>Some time after supper.</para></listitem>
+ <listitem><para>Use GNU Solfege to test your ability to perceive musical rudiments.</para></listitem>
+ <listitem><para>Spend only a few minutes on a few different kinds of exercises.</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Three ten-minute segments is not a lot of time, and indeed it may take additional time to plan and to find and set up materials. Even so, the point is that training your aural skills does not have to take an inordinate amount of time or effort. What's important is that your effort is consistent and well-planned.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Training-Supplementary_References">
+ <title>Supplementary References</title>
+ <para>
+ GNU Solfege offers a relatively wide variety of exercises, but no one source can possibly offer all of the exercises and training required to develop a well-rounded set of aural skills. Some of the following books and activities should be used to supplement the exercises available in "Solfege." Note that melodic and harmonic dictation are not yet "Solfege's" strong points, mostly due to a lack of different exercises. This may improve in the future, as the developers improve the software.
+ </para>
+ <para>
+ Activities:
+ <itemizedlist>
+ <listitem><para>Taking dictation from real music. Try focussing on one element, rather than writing a complete score. Verify your solution by checking a published score if possible. Remember that some orchestral instruments may not be written at concert pitch.</para></listitem>
+ <listitem><para>Using your sight-singing skills to sing a melody or rhythm to a friend, who can use it as an example for dictation.</para></listitem>
+ <listitem><para>Use Bach chorales as sight-singing examples for a group of four or more people. It helps to have friends in all vocal ranges, but it isn't necessary. Remember to use solfa syllables, and avoid the chorale's text.</para></listitem>
+ <listitem><para>If a mechanical device, like a fan, is emitting a constant pitch, you can practice singing harmonic intervals with that device.</para></listitem>
+ <listitem><para>Perform exercises for your friends - long and short - on different instruments. This will help to build competence in musical contexts more realistic than a computer can provide, but still in an isolated situation.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ !! This is probably going to be a bibliography list, once I found out how to do that !!
+ Books:
+ * Hindemith, Paul (1949). ''Elementary Training for Musicians''. Schott.
+ ** Antiquated instructions, but the exercises are excellent.
+ ** Offers a wide variety of exercises and strategies, especially for coordination of quasi-independent musical lines.
+ ** In particular, Hindemith avoids the use of solfa syllables; modern practice uses them anyway.
+ * Karpinski, Gary (2007). ''Manual for Ear Training and Sight Singing''. Norton.
+ ** Contains chapters with detailed theoretical explanations, tips for listening, and developmental exercises.
+ ** Comes with a CD containing listening exercises; possibly incompatible with Linux.
+ * Karpinski, Gary. ''Anthology for Sight Singing''. Norton: 2006.
+ ** Organized by chapter to coincide with the above ''Manual''.
+ ** Contains examples that can be used to train one's ear by singing.
+ ** It is best to play only the tonic tone (not a chord or scale) on a keyboard instrument before singing. Only after you are sure that you have sung the excerpt correctly by ear should it be played on a keyboard instrument for verification.
+ ** Contains some ensemble excerpts, to be sung by a group of people who are working on ear training together.
+ * Hall, Anne (2004). ''Studying Rhythm''. Prentice Hall.
+ ** Similar in principle to Karpinski's ''Anthology'': contains one- and two-part rhythms to be spoken or spoken-and-clapped. Also contains some 3- and 4-part rhythms.
+ ** Progresses incrementally from easy-to-perform rhythms to more difficult ones.
+ ** Offers some performance tips.
+ ** Provides a few ensemble rhythms to be performed by a group of people working on ear training; all two-part rhythms can also be treated as ensemble rhythms.
+ * Crowell, Ben (2004). ''Eyes and Ears: an Anthology of Melodies for Sight-Singing''.
+ ** An open-source sight-singing text, available free from [http://www.lightandmatter.com/sight/sight.html here].
+ ** Contains about 400 melodies from the public domain, and some instructions.
+ * Hoffman, ''The Rhythm Book''. Smith Creek Music, 2009.
+ </para>
+ </section>
+ </section> <!-- Ends "How to Train Yourself" Section --> <!-- Solfege-Training- -->
+ <section id="sect-Musicians_Guide-Solfege-Listening_Exercises">
+ <title>How to Use Listening Exercises</title>
+ <procedure>
+ <step><para>Open the software</para></step>
+ <step><para>It is at the "Front Page"</para></step>
+ <step><para>Decide which type of exercise to do</para></step>
+ <step><para>Decide which sub-section to focus on</para></step>
+ <step><para>Click "New" or "New Interval" or whatever to get the first question</para></step>
+ <step><para>On some exercises, you need to click "new" whenever you want a new one</para></step>
+ <step><para>Some exercises can be configured to automatically provide a new question when you correctly answer the previous one</para></step>
+ <step><para>After hearing each exercise, try to make a correct identification.</para></step>
+ <step><para>If you need to hear the exercise again, do it.</para></step>
+ <step><para>It is good to limit the number of times you listen.</para></step>
+ <step><para>Select what you think is the correct choice.</para></step>
+ <step><para>Go to the next question, which may be automatic for some questions. You may want to pre-select a number of seconds to wait before progressing to the next question.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-Singing_Exercises">
+ <title>How to Use Singing Exercises</title>
+ <para>
+ These are:
+ "Sing intervals"
+ </para>
+ <procedure>
+ <step><para>Select "Sing intervals"</para></step>
+ <step><para>Choose which ones you want to focus on</para></step>
+ <step><para>The exercise will begin, playing the first of the tones you are to sing</para></step>
+ <step><para>You must sing the first and the second tone, or to make it harder, only the second tone (tip: use sol-fa syllables!)</para></step>
+ <step><para>Solfege does not know whether you sang the interval correctly, so you must tell it.</para></step>
+ </procedure>
+ <para>
+ "Tap generated rhythm"
+ </para>
+ <procedure>
+ <step><para>Select "Tap generated rhythm"</para></step>
+ <step><para>Choose a subcategory (they correspond to those in the dictation, but there is no compound metre available). See below.</para></step>
+ <step><para>Click "New"</para></step>
+ <step><para>It will play you a rhythm; listen carefully, and conduct the beat if you can.</para></step>
+ <step><para>as with rhythmic dictation, you will be given an intro</para></step>
+ <step><para>You must repeat the rhythm by click on the "Tap here" button</para></step>
+ <step><para>Best to use the space bar to tap in; here's how.</para></step>
+ <step><para>The "accuracy" may be set too high; I like 0.30</para></step>
+ <step><para>On "Config," change "Number of beats in question" to adjust the difficulty</para></step>
+ </procedure>
+ <para>
+ "Sing chord"
+ </para>
+ <procedure>
+ <step><para>Select "Sing chord"</para></step>
+ <step><para>Choose the type of chords you want to sing</para></step>
+ <step><para>Click "New"</para></step>
+ <step><para>Solfege will automatically play an "A" for you, and you can hear it again by clicking, "440hz"</para></step>
+ <step><para>Sing the chord ascending</para></step>
+ <step><para>Verify that you sang correctly by clicking "Play answer" and hearing whether the pitches are the same.</para></step>
+ <step><para>Click "New" for another question</para></step>
+ <step><para>On the "Config" tab, it allows you to change how far it will transpose the built-in models; best to leave this as it is <code>['key', -5, 5]</code></para></step>
+ <step><para>Solfege does not know whether you sang the interval correctly, so you must tell it.</para></step>
+ </procedure>
+ <para>
+ "Sing chord tone"
+ </para>
+ <procedure>
+ <step><para>Select "Sing chord tone"</para></step>
+ <step><para>Select which chordal member you want to practise singing</para></step>
+ <step><para>Click "New"</para></step>
+ <step><para>Solfege will display and play a chord in blocked form, and you must sing the chord member that it tells you to sing.</para></step>
+ <step><para>You can repeat the chord in blocked form ("Repeat") or in arpeggio form ("Repeat arpeggio"). It is much easier to hear a chord played in arpeggio form, so we recommend that you practice both ways.</para></step>
+ <step><para>When you are sure that you correctly sang the chord member, click "Play answer"</para></step>
+ <step><para>For the next question, click "New"</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-Configure_Yourself_Exericses">
+ <title>How to Use "Configure Yourself" Exercises</title>
+ <para>
+ These exercises allow you to choose the focus of your training, rather than using a Solfege preset. When you enter an exercise, you are given a default setup, which is then customized on the "Config" tab in the activity. The following things are customizeable in "Configure Yourself" exercises, but not in the other counterparts:
+ </para>
+ <para>
+ "Harmonic intervals" allows you to de/select specific intervals between m2 and M10
+ </para>
+ <para>
+ "Melodic intervals" and "Sing intervals" allow you to de/select specific intervals between m2 and M10, and whether to test them up, down, or both.
+ </para>
+ <para>
+ "Compare intervals" allows you to select specific intervals between minor second and major tenth. Also allows you to switch between harmonic or melodic intervals independently for the first and second interval.
+ </para>
+ <para>
+ "Id tone": allows you to choose a "weighting" for each pitch, to conentrate on specific ones. Also allows you to adjust octave displacement to higher or lower octaves.
+ </para>
+ <para>
+ For all of the rhythm exercises, "binary time" means "simple metre," and "ternary time" means "compound metre." All sections allow you to choose which single-beat rhythms to use when creating the question.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Rhythm_Exercises">
+ <title>How to Use "Rhythm" Exercises</title>
+ <para>
+ This is dictation or play-back. The rhythms described in this section use the "takadimi" rhythm system, which is explained [http://www.takadimi.net/takadimiArticle.html here]. You can use any rhythm system you prefer.
+ </para>
+ <para>
+ For Rhythmic Dictation:
+ </para>
+ <procedure>
+ <step><para>Click "Rhythm"</para></step>
+ <step><para>Choose which subcategory:
+ <itemizedlist>
+ <listitem><para>Rhythms (easy) is: quarter, 2x eighths, 4x sixteenths</para></listitem>
+ <listitem><para>Rhythms is: those plus ka-di-mi, ta-ka-mi, ta-ka-di, ta-mi, and ta-ka</para></listitem>
+ <listitem><para>Rhythms (difficult) is: those plus rests and triplets</para></listitem>
+ <listitem><para>Rhythms in 3/4 is: compound metre everything</para></listitem>
+ </itemizedlist>
+ </para></step>
+ <step><para>Click "New" to get a new question</para></step>
+ <step><para>Click the buttons above the "Play" button to input the rhythm-units, in order from start to finish</para></step>
+ <step><para>Use paper to work it out</para></step>
+ <step><para>If you make a mistake inputting, use the "Backspace" button</para></step>
+ <step><para>You can "Repeat" to hear it again - not too many times!</para></step>
+ <step><para>You can change the difficulty by increasing the number of beats per question, on "Config" tab</para></step>
+ <step><para>If you get a question wrong, you will have a chance to correct it; the incorrect parts are underlined for you in red</para></step>
+ </procedure>
+ <para>
+ For Rhythmic Tap-Back, see above section "Singing Exercises."
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Dictation_Exercises">
+ <title>How to Use "Dictation" Exercises</title>
+ <para>
+ These dictation exercises are for melodic dictation. There is not a great variety of examples here, and they are either easy or difficult, with no middle-ground.
+ </para>
+ <procedure>
+ <step><para>Click "Dictation"</para></step>
+ <step><para>Choose a level:
+ <itemizedlist>
+ <listitem><para>Volkslieder 1: German folk songs (easy)</para></listitem>
+ <listitem><para>Volkslieder 2: German folk songs (easy)</para></listitem>
+ <listitem><para>Parts of 2 Bach inventions: only 2; the hardest of the four categories</para></listitem>
+ <listitem><para>Norwegian children songs: only 3 (easy)</para></listitem>
+ </itemizedlist>
+ </para></step>
+ <step><para>The clef, key and time signatures are given for you, along with the starting note, and title.</para></step>
+ <step><para>The quarter-note buttons allow you to play only part of the melody.</para></step>
+ <step><para>"Play the whole music" plays both parts of the music.</para></step>
+ <step><para>"Back" and "Forward" shifts through the excerpts for dictation.</para></step>
+ <step><para>It's best to "Play the whole music" as many times as needed (5 - 7 or less maximum, depending on the excerpt).</para></step>
+ <step><para>It's best to avoid playing only part of the music.</para></step>
+ <step><para>Write down the excerpt on paper, then when you're sure that you've finished it correctly, click "Show."</para></step>
+ <step><para>This exercise is self-policing, and does not track progress.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Harmonic_Progressions">
+ <title>How to Use "Harmonic Progressions" Exercises</title>
+ <para>
+ These dictation exercises are for harmonic dictation. You will be asked to guess the harmonic progression, but users should also notate at least the outer voices (lowest and highest). It should be noted that these progressions do not follow Common Practice Period harmonic procedures.
+ </para>
+ <procedure>
+ <step><para>Click "Harmonic progressions"</para></step>
+ <step><para>Some harmonic progressions require MMA (as indicated). See below for instructions on installation.</para></step>
+ <step><para>The Non-MMA Categories contain the following chords:
+ <itemizedlist>
+ <listitem><para>"Easy harmonic progressions": I, II, IV, V, VI</para></listitem>
+ <listitem><para>with Inverisons: add IV6 and V6</para></listitem>
+ <listitem><para>"Three chords, root position": I, II, III, IV, V, VI</para></listitem>
+ </itemizedlist>
+ </para></step>
+ <step><para>Choose a category.</para></step>
+ <step><para>Click "New" to get a question.</para></step>
+ <step><para>The passage will automatically play once, but you will not get a key signature. If you are notating the dictation, and you do not know which pitches are being used, then you may wish to guess the key, using sol-fa equivalents to know if you're correct.</para></step>
+ <step><para>Click the chord-buttons to input the series of chords that you hear, in order from first to last.</para></step>
+ <step><para>To hear the example again, click "Repeat."</para></step>
+ <step><para>If you make a mistake, click the "Backspace" button to erase the last-input chord.</para></step>
+ <step><para>When you are sure that your answer is correct, click "Guess answer."</para></step>
+ <step><para>To get another question, click "New".</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-Solfege-Intonation">
+ <title>How to Use "Intonation" Exercises</title>
+ <para>
+ In order to use the Intonation exercises, you must install the "Csound" application. Instructions are located [[User:Crantila/FSC/Solfege#Optional Installation: Csound|here]].
+ </para>
+ <procedure>
+ <step><para>Click on "Intonation"</para></step>
+ <step><para>All of the exercises test an ascending perfect fifth. The closer the number is to 1.0, the less the difference when it is out-of-tune.</para></step>
+ <step><para>Click "New" to get a new question.</para></step>
+ <step><para>The interval will automatically play.</para></step>
+ <step><para>Click "Repeat" to repeat the interval.</para></step>
+ <step><para>You must choose whether the second tone is flat (the interval is too small), in tune (the interval is the right size), or sharp (the interval is too large).</para></step>
+ <step><para>When you are sure of your answer, click the corresponding button.</para></step>
+ <step><para>To get the next question, click "New."</para></step>
+ </procedure>
+ </section>
+</chapter>
diff --git a/en-US/SuperCollider/SuperCollider-Basic_Programming.xml b/en-US/SuperCollider/SuperCollider-Basic_Programming.xml
new file mode 100644
index 0000000..c5b6410
--- /dev/null
+++ b/en-US/SuperCollider/SuperCollider-Basic_Programming.xml
@@ -0,0 +1,2805 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<!-- SC-Basic_Programming- -->
+
+<section id="sect-Musicians_Guide-SuperCollider-Basic_Programming">
+ <title>Basic Programming in SuperCollider</title>
+ <para>
+ As with any programming language, you will start learning SuperCollider with the basic commands, that are of little use by themselves. However, since the language is so flexible, even the most basic commands can be combined in ways that create highly complex behaviours. The example program, "Method One," was written with the goal of illustrating how a single sound-generating object can be used to create an entire composition. This tutorial does not begin with audio-generating code, which helps to emphasize that SuperCollider is primarily a programming language.
+ </para>
+ <para>
+ This portion of the Guide is designed as a "reference textbook," which you can use both to learn the SuperCollider language in the first place, and to remind yourself about the language's features afterwards.
+ </para>
+ <para>
+ The Guide will probably be most effective when read only in small portions at once.
+ </para>
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-First_Steps">
+ <title>First Steps</title>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-First_Steps-Parts_of_SuperCollider">
+ <title>The Different Parts of SuperCollider</title>
+ <para>
+ As you discovered when installing SuperCollider, there are actually many different components involved with SuperCollider. Here is a list of some of them, with brief descriptions of their purpose:
+ <itemizedlist>
+ <listitem><para>Programming language: this is an abstract set of rules and guidelines that allow you to write down instructions for producing sounds.</para></listitem>
+ <listitem><para>Interpreter: this is what is run in GEdit; it transforms the "programming language" instructions written by you into useful instructions for the server; also called the "client."</para></listitem>
+ <listitem><para>Server: this is what synthesizes the sound, according to instructions sent to it by the interpreter.</para></listitem>
+ <listitem><para>Library: these contain commands and the instructions to be executed when you call the commands; the interpreter looks up commands in the library when you call them.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ This modular design allows for several advanced capabilities and features. Any particular element could theoretically be replaced without affecting other elements, as long as the methods of communication remain the same. As long as the programming language is the same, portions of the library can be modified, removed, or added at will; this happens often, and Planet CCRMA at Home provides a collection of library extensions. One of the most exciting capabilities is the ability to run the interpreter and server on different physical computers. The networking component is built into these components - they always communicate by UDP or TCP, even when run on the same computer! Although this ability is not used in this Guide, it is not difficult.
+ </para>
+ <para>
+ The most important thing to remember is that the SuperCollider interpreter is what deals with the programs you write. The SuperCollider server is controlled by the interpreter, but is an independent program. For simple things, like the Hello World Programs below, the server is not even used - after all, there is no audio for it to synthesize.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-First_Steps-Hello_World">
+ <title>"Hello, World!"</title>
+ <para>
+ The first program that one traditionally makes when learning a new programming language is called "The Hello World Program." This is a simple and trivial application that simply prints outs the phrase, "Hello, World!" (or any variation of it). It might seem useless at first, but the ability to provide feedback to an application's user is very important, and this is essentially what the Hello World Program does.
+ </para>
+ <para>
+ Here is the program in SuperCollider:
+ [pre]
+ "Hello, World!".postln;
+ [/pre]
+ </para>
+ <para>
+ Here is an extension to that program:
+ [pre]
+ "Hello, World!".postln;
+ "Hello, SC!".postln;
+ [/pre]
+ </para>
+ <para>
+ As with all examples in this Guide, you should paste these programs into GEdit, and execute them with SuperCollider. Look at the output produced by the programs, but don't worry about it for now.
+ </para>
+ <para>
+ These programs are very small, but it highlights some key concepts of the SuperCollider language, described below.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-First_Steps-Return_Values">
+ <title>Return Values</title>
+ <para>
+ Every SuperCollider program must provide the interpreter with a value (some information) when it has carried out all of its instructions. This value is called a "return value," because it is the value given by a program when it "returns" control to the interpreter. In a SuperCollider program, it is the last value stated in a program that automatically becomes the return value - no special command is required. When program execution ends, and control is returned to the SuperCollider interpreter, the interpreter outputs the return value in the "SuperCollider output" pane.
+ </para>
+ <para>
+ In the single-line Hello World Program above, the program produces the following output:
+ [pre]Hello, World!
+ Hello, World![/pre]
+ The program appears to have been executed twice, but that is not the case. The first "Hello, World!" is printed by the program. The second "Hello, World!" appears because <code>"Hello, World!.postln</code> is the last (in this case, the only) value of the program. It is "returned" by the program, and the interpreter prints it.
+ </para>
+ <para>
+ In the two-line Hello World Program above, the program produces the following output:
+ [pre]
+ Hello, World!
+ Hello, SC!
+ Hello, SC!
+ [/pre]
+ This makes it more clear that the program is not being executed twice, and that it is the last value of a program that is returned to the interpreter.
+ </para>
+ <para>
+ Try executing the following single-line programs. Look at the output produced by each, and determine whether it is printed by the program itself, the interpreter, or both.
+ <itemizedlist>
+ <listitem><para><code>"Hello, World!".postln;</code></para></listitem>
+ <listitem><para><code>"Hello, World!";</code></para></listitem>
+ <listitem><para><code>5.postln;</code></para></listitem>
+ <listitem><para><code>5;</code></para></listitem>
+ </itemizedlist>
+ Can you modify the two-line Hello World Program so that each line is printed only once?
+ </para>
+ <para>
+ Note: In reality, every "function" must return a value. Functions are described later in this Guide; the difference is not yet important.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-First_Steps-Statements">
+ <title>Statements</title>
+ <para>
+ A "statement" is a single instruction, which is always ended with a semicolon. Exactly what constitutes a statement will become clear as you gain experience, and including semicolons will quickly become an automatic action.
+ </para>
+ <para>
+ In the Hello World Programs above, all of the statements contain the single instruction to post a line to the output screen. What happens when you remove the first semicolon, which marks the end of the first statement? The SuperCollider interpreter produces an unhelpful error message, and tells you that an error occurred ''after'' the forgotten semicolon. This is why it is important to always remember statement-concluding semicolons.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-First_Steps-Numbers_and_Strings">
+ <title>Data Types: Numbers and Strings</title>
+ <para>
+ In many programming languages, it is the programmer's responsibility to determine the type of data that is being used, and how it should be stored. The SuperCollider interpreter takes advantage of the power of modern computers, and deals with this on our behalf. This greatly simplifies basic tasks, because there are only two kinds of data to worry about, and they make perfect sense:
+ <itemizedlist>
+ <listitem><para>Numbers: These are numbers, written simply as numbers. Anything that can be done with real-world numbers can also be done with SuperCollider's numbers. They can be as large or small, positive or negative as you want. They can have any number of digits on either side of the decimal point.</para></listitem>
+ <listitem><para>Strings: These are a string of characters, written between two double-quote characters like "this." The double-quote characters are required so that SuperCollider knows where to begin and end the string of characters. A string of character can contain as many characters as you like, including one character and no characters. If you want to include a double-quote character in a string, you should put a blackslash before it. The following is interpreted by SuperCollider as a string with only a double-quote character: <code>"\""</code></para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Here are some examples of numbers and strings:
+ <itemizedlist>
+ <listitem><para><code>5;</code></para></listitem>
+ <listitem><para><code>18920982341;</code></para></listitem>
+ <listitem><para><code>0.00000000000001;</code></para></listitem>
+ <listitem><para><code>"characters";</code></para></listitem>
+ <listitem><para><code>"@";</code></para></listitem>
+ <listitem><para><code>"";</code></para></listitem>
+ <listitem><para><code>"6";</code></para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Is the last example a number or a string? You and I recognize that it is a number inside a string, but SuperCollider will only treat it as a string. You can do string things with it, but you cannot do number things with it. You cannot add <code>"6"</code> to something, for example. Notice also that each example ends with a semicolon, which makes them complete statements. The statements don't do anything but represent themselves.
+ </para>
+ <para>
+ Try executing the following single-line programs. Think about why the SuperCollider interpreter produces the output that it does.
+ <itemizedlist>
+ <listitem><para><code>6 + 3;</code></para></listitem>
+ <listitem><para><code>"6" + 3;</code></para></listitem>
+ <listitem><para><code>"six" + 3;</code></para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-First_Steps-Consecutive_Execution">
+ <title>Consecutive Execution</title>
+ <para>
+ Complex SuperCollider programs contain many parts, which all do different things. Sometimes, executing all of these together doesn't make sense, and it can be difficult to know which portions of the program are supposed to be executed when. To help with this, the interpreter allows you to mark portions of your program between ( and ) so that you will know to execute them together.
+ </para>
+ <para>
+ Here is an example:
+ [pre]
+ (
+ "Hello, Fred!".postln;
+ "Hello, Wilma!".postln;
+ )
+ (
+ "Goodbye, Fred!".postln;
+ "Goodbye, Wilma!".postln;
+ )
+ [/pre]
+ It doesn't make sense to say "hello" and "goodbye" at the same time, so separating these sections with parentheses will serve as a reminder. In case we try to execute all of the code at once, the SuperCollider interpreter will give us an error.
+ </para>
+ </section>
+ </section> <!-- Ends "First Steps" Section --> <!-- SC-Basic_Programming-First_Steps- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Variables_and_Functions">
+ <title>Variables and Functions</title>
+ <para>
+ The concepts in this section are related to the mathematical terms with the same names. This is a modern-day result of the first uses of computers and programming languages: the calculation of complex mathematical problems.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Variables_and_Functions-Variables">
+ <title>Variables</title>
+ <para>
+ A variable is a symbol that can be assigned an arbitrary value. A "symbol" is a series of alphabetic and numeric characters, separated by whitespace (a space, a line-break, or the end of the file). When a variable is "assigned" a value, the variable name (the symbol) is understood to be a substitute for the assigned value.
+ </para>
+ <para>
+ Consider a traffic light, which has three possible symbols: green, yellow, and red. When you are driving, and you encounter a traffic light, you might see that its red symbol is activated (the red light is illuminated). What you see is a red light, but you understand that it means you should stop your car. Red lights in general do not make you stop - it is specifically red traffic lights, because we know that it is a symbol meaning to stop.
+ </para>
+ <para>
+ SuperCollider's variables work in the same way: you tell the interpreter that you want to use a symbol, like <code>cheese</code>. Then you assign <code>cheese</code> a value, like <code>5</code>. After that point, whenever you use <code>cheese</code>, the interpreter will automatically know that what you really mean is <code>5</code>.
+ </para>
+ <para>
+ Run the following two programs. They should result in the same output.
+ [pre]
+ (
+ 5 + 5;
+ )
+ [/pre]
+ [pre]
+ (
+ var cheese;
+ cheese = 5;
+ cheese + cheese;
+ )
+ [/pre]
+ </para>
+ <para>
+ In the first example, the program calculates the value of <code>5 + 5</code>, which is <code>10</code>, and returns that to the interpreter, which prints it out. In the second example, the program tells the interpreter that it wants to use a variable called <code>cheese</code> then it assigns cheese the value <code>5</code>. Finally, the program calculates <code>cheese + cheese</code>, which it understands as meaning <code>5 + 5</code>, and returns <code>10</code> to the interpreter, which prints it out.
+ </para>
+ <para>
+ This trivial use of a variable does nothing but complicate the process of adding 5 to itself. Soon you will see that variables can greatly simplify your programs.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Variables_and_Functions-Using_Variables">
+ <title>Using Variables</title>
+ <para>
+ There are three words that describe the key stages of using a variable: declaration, initialization, and assignment.
+ </para>
+ <para>
+ A variable must be declared before use, so that the interpreter knows that you want to use that symbol as a variable. All variables must be declared before any statement that does not declare a variable; in other words, you should declare your variables before doing anything else. Variable names are declared like this:
+ [pre]var variableName;[/pre]
+ Variables can also be declared in lists, like this:
+ [pre]var variableOne, variableTwo;[/pre]
+ </para>
+ <para>
+ Variables can be assigned a value at any time after they have been declared. Any single object can be assigned to a variable. If a variable is already assigned a value, any subsequent assignment will erase the previous assignment; the previously-assigned value will is not retrievable.
+ </para>
+ <para>
+ The first assignment to a variable is said to "initialize" the variable. Initialization is a special kind of assignment, because a variable cannot be used before it is initialized. If a program attempts to use an un-initialized variable, the SuperCollider interpreter will cause an error. For this reason, you should always initialize a variable when you declare it. There is a special way to do this:
+ [pre]var variableName = nil;[/pre]
+ Since you can't always assign a useful value, you can pick an arbitrary one. Assigning "nil" is common practice, because it means "nothing," but without actually being nothing (this avoids ''some'' errors). Assigning zero is another possibility; it is standard practice in many programming languages, and will avoid most errors, even if the variable is eventually supposed to hold another kind of object. Intialization and declaration of multiple variables can also be done as a list:
+ [pre]var variableOne = 0, variableTwo = 0;[/pre]
+ </para>
+ <para>
+ Single-letter variable names have a special purpose in SuperCollider. They are already declared, so you don't have to declare them. They are also already initialized to "nil", so you don't have to do that either. These variable names are intended to be used as a quick fix, while you're experimenting with how to make a program work. You should not use them in good-quality programs.
+ </para>
+ <para>
+ The single-letter variable "s" is automatically assigned to the server on the computer running the interpreter. You should avoid re-assigning that variable.
+ </para>
+ <para>
+ Variable names must always begin with a lower-case letter.
+ </para>
+ <para>
+ Use variables to write programs that do the following tasks:
+ <orderedlist>
+ <listitem><para>Perform arithmetic with an uninitialized variable. An error should appear when the program is executed.</para></listitem>
+ <listitem><para>Calculate the value of <code>y</code>, if all other values are known, for the quadratic equation: <code>y = a * x * x + b * x + c</code></para></listitem>
+ <listitem><para>Re-write the Hello World Program so that it will say "Hello" to a name stored in a variable. Remember that you can use the interpreter to automatically output the last line of a function.</para></listitem>
+ </orderedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Variables_and_Functions-Functions">
+ <title>Functions</title>
+ <para>
+ A Function is a statement, or a series of statements, that we want to use many times. When a Function is assigned to a variable, you can execute the Function as many times as you wish. Any statements that happen between braces { like this; } are treated as a Function. Functions are executed by passing them the "value" message, as in the following example.
+ </para>
+ <para>
+ Here is a Function that is not assigned to a variable, and is executed once.
+ [pre]{ "Hello, World!".postln; }.value;[/pre]
+ Notice that there are two semicolons: one after the statement within the Function, and one after the "value" message that tells the Function to execute.
+ </para>
+ <para>
+ Here is a Function with identical function, assigned to a variable, and executed twice.
+ [pre]
+ var myFunction = { "Hello, World!".postln; }; // note two semicolons
+ myFunction.value;
+ myFunction.value;
+ [/pre]
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Variables_and_Functions-Function_Arguments">
+ <title>Function Arguments</title>
+ <para>
+ The most useful aspect of Functions is that they can produce varying results, depending on their input. For whatever reason, the input accepted by a Function is called an "argument." SuperCollider's Functions can accept any number of arguments - zero, one, or many. Argument values (called "parameters") are provided to a Function by adding them in parentheses after the name of the Function, separated with commas, like this: <code>exampleFunction( 5, 7, 9 );</code> Argument variables are declared as the first statement in a Function, like this: <code>arg oneNumber, twoNumber;</code>
+ </para>
+ <para>
+ This program is significantly more complicated than previous examples, but it shows how useful Functions can be. Notice how the braces in that example are on different lines than the rest of the Function, which gives us more space within the Function to complete some useful work.
+ [pre]
+ (
+ var greeter =
+ {
+ arg name;
+ ( "Hello" + name ).postln;
+ };
+
+ greeter.value( "Samantha" );
+ greeter.value( "Jermain" );
+ nil;
+ )
+ [/pre]
+ Here is how the program works:
+ <orderedlist>
+ <listitem><para>A variable named <code>greeter</code> is declared, and assigned a Function.</para></listitem>
+ <listitem><para>The Function contains an argument called <code>name</code>, and outputs "Hello" plus the name given to it.</para></listitem>
+ <listitem><para>The parentheses here <code>( "Hello" + name )</code> ensure that the two strings are added together ''before'' the "postln" message prints them out.</para></listitem>
+ <listitem><para>The <code>greeter</code> variable is used to call the Function with two different names.</para></listitem>
+ <listitem><para>The <code>nil;</code> statement is optional, and does not affect the operation of the program. What it does is return a "nothing" value to the interpreter after program execution completes, so that the last message is not repeated.</para></listitem>
+ </orderedlist>
+ </para>
+ <para>
+ Since every argument has a name, SuperCollider allows you to use that name when executing the Function. This example executes the <code>greeter</code> Function from the last example:
+ [pre]greeter.value( name:"Myung-Whun" );[/pre] This is more useful if there are many arguments, and you do not remember the order that they appear in the Function's definition.
+ </para>
+ <para>
+ SuperCollider also allows you to specify default values for arguments, so that they do not need to be specified. This allows optional customization of a Function's behaviour, and is therefore very powerful.
+ </para>
+ <para>
+ This example modifies the one above by adding default-value arguments, and by calling arguments with their name. As you can see, I've been tricking you a bit: <code>postln</code> is actually a Function, but a special kind, explained later.
+ [pre]
+ (
+ var greeter =
+ {
+ arg name, greeting = "Hello";
+ postln( greeting + name );
+ };
+
+ greeter.value( "Samantha" );
+ greeter.value( "Jermain", "Goodbye" );
+ greeter.value( name:"Myung-Whun" );
+ greeter.value( greeting:"Bienvenue", name:"Marcel" );
+ nil;
+ )
+ [/pre]
+ </para>
+ <para>
+ Any value can be used as a parameter, as long as the Function expects it. In fact, even Functions can be used as parameters for Functions!
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Variables_and_Functions-Function_Return_Values">
+ <title>Function Return Values</title>
+ <para>
+ All SuperCollider Functions return a value to the interpreter when they have finished execution. As with programs, the value returned is the value of the last statement in the Function. The return value of a Function can be captured, assigned to a variable, and used again later.
+ </para>
+ <para>
+ This example assigns the result of a Function to a variable.
+ [pre]
+ (
+ var mysticalMath =
+ {
+ arg input = 0;
+ input * 23;
+ };
+ var someNumber = 9;
+
+ someNumber = mysticalMath.value( someNumber );
+ someNumber.postln;
+ nil;
+ )
+ [/pre]
+ Here is how the program works:
+ <orderedlist>
+ <listitem><para>A Function and variable are created, and assigned values.</para></listitem>
+ <listitem><para>This line <code>someNumber = mysticalMath.value( someNumber );</code> executes the <code>mysticalMath</code> Function, which multiplies its argument by 23 and returns the value. Then, it assigns the return value of the Function to <code>someNumber</code>. In any statement that contains an assignment, the assignment is always done last. In other words, the Function in this example will ''always'' be given an argument of <code>9</code>, and only ''after'' the Function completes execution and returns a value will that value be assigned to <code>someNumber</code>.</para></listitem>
+ <listitem><para>The new value of <code>someNumber</code> is displayed.</para></listitem>
+ </orderedlist>
+ </para>
+ <para>
+ The program could have been shortened like this:
+ [pre]
+ (
+ var mysticalMath =
+ {
+ arg input = 0;
+ input * 23;
+ };
+
+ var someNumber = mysticalMath.value( 9 );
+ someNumber.postln;
+ nil;
+ )
+ [/pre]
+ </para>
+ <para>
+ It could have been shortened even more like this:
+ [pre]
+ (
+ var mysticalMath =
+ {
+ arg input = 0;
+ input * 23;
+ };
+
+ mysticalMath.value( 9 ).postln;
+ nil;
+ )
+ [/pre]
+ </para>
+ <para>
+ Experiment with the shortened versions of the program, ensuring that you know why they work.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Variables_and_Functions-">
+ <title>Variable Scope</title>
+ <para>
+ A variable is only valid within its "scope." A variable's scope is determined by where it is declared. It will always last between either ( and ) or { and }, and applies to all statements within that block of code. Variable names can be re-declared in some contexts, which can be confusing.
+ </para>
+ <para>
+ Consider the scope of the variables in this example:
+ [pre]
+ (
+ var zero = 0;
+ var function =
+ {
+ var zero = 8;
+ var sixteen = 16;
+ zero.postln; // always prints 8
+ };
+
+ function.value;
+ zero.postln; // always prints 0
+ sixteen.postln; // always causes an error
+ )
+ [/pre]
+ Because <code>function</code> declares its own copy of <code>zero</code>, it is modified independently of the variable <code>zero</code> declared before the Function. Every time <code>function</code> is executed, it re-declares its own <code>zero</code>, and the interpreter keeps it separate from any other variables with the same name. When <code>function</code> has finished executing, the interpreter destroys its variables. Variables declared inside any Function are only ever accessible from within that Function. This is why, when we try to execute <code>sixteen.postln;</code>, the interpreter encounters an error: <code>sixteen</code> exists only within <code>function</code>, and is not accessible outside the Function. By the way, in order to excute this example, you will need to remove the error-causing reference to <code>sixteen</code>.
+ </para>
+ <para>
+ Now consider the scope of the variables in this example:
+ [pre]
+ (
+ var zero = 0;
+ var function =
+ {
+ var sixteen = 16;
+ zero = 8;
+ zero.postln; // always prints 8
+ sixteen.postln;
+ };
+
+ function.value;
+ zero.postln; // always prints 8
+ )
+ [/pre]
+ Why does the last line always print <code>8</code>? It's because <code>zero</code> was set to 8 within <code>function</code>. More importantly, <code>function</code> did not declare its own copy of <code>zero</code>, so it simply accesses the one declared in the next "highest" block of code, which exists between ( and ) in this example.
+ </para>
+ <para>
+ This is why it's important to pay attention to a variable's scope, and to make sure that you declare your variables in the right place. Unexpected and difficult-to-find programming mistakes can occur when you forget to declare a variable, but it is declared elsewhere in your program: you will be allowed to use the variable, but it will be modified unexpectedly. On the other hand, it can be greatly advantageous to be able to access variables declared "outside the local scope" (meaning variables that aren't declared in the same code block in which they're used), but careful thought and planning is required.
+ </para>
+ <para>
+ Astute readers will notice that it is possible to re-declare the single-letter variable names, allowing you to control their scope. Consider the following program:
+ [pre]
+ (
+ var a = 0;
+ b =
+ {
+ var c = 16;
+ a = 8;
+ a.postln;
+ c.postln;
+ };
+
+ b.value;
+ a.postln;
+ )
+ [/pre]
+ This example requires careful examination. What is the scope of <code>a</code>, <code>b</code>, and <code>c</code>? The answers may be surprising.
+ <itemizedlist>
+ <listitem><para><code>a</code> is declared just after the ( character, so the interpreter destroys it upon reaching the ) character.</para></listitem>
+ <listitem><para><code>c</code> is declared just after the { character, so the interpreter destroys it upon reaching the } character.</para></listitem>
+ <listitem><para><code>b</code> is ''not'' declared in this program, so it refers to the automatically-declared variable with that name. The interpreter does not destroy it until it is restarted or stopped. This means that the Function assigned to <code>b</code> is still available ''after'' the program finishes execution. Try it! Execute the program above, and then execute this single-line program alone: <code>b.value;</code></para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ </section> <!-- Ends "Variables and Functions" Section --> <!-- SC-Basic_Programming-Variables_and_Functions- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Object_Oriented">
+ <title>Object-Oriented SuperCollider</title>
+ <para>
+ SuperCollider is difficult to describe precisely, because its syntax allows great flexibility. There are many different ways to accomplish the same task. Each one is subtly different, and gives you a different set of possibilities, but there is often no "best solution." One of the advantages to this is that it easily allows three "programming paradigms," although one is used much more often than the others.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Object_Oriented-Imperative_Programming">
+ <title>Imperative Programming</title>
+ <para>
+ Imperative programming is easy to understand: it is simply a list of commands, like this:
+ [pre]
+ (
+ var a, b, c;
+
+ a = 12;
+ b = 25;
+ c = a + b;
+ a.postln;
+ )
+ [/pre]
+ Declare the variables, set the variables, do a calculation, and print the result of the calculation. This is a simple example, and a simple model, but it is very difficult to escape completely. After all, humans think of large problems in terms of algorithms (the instructions needed to do something). Computers solve large problems, so being able to program them with a series of instructions makes sense.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Object_Oriented-Functional_Programming">
+ <title>Functional Programming</title>
+ <para>
+ Functional programming is also easy to understand, but it can be a little bit more difficult to think about complex tasks. Functional programs use Functions to complete all of their work. This is not strictly possible in SuperCollider: it is more imperative than functional, but the creative use of Functions can easily solve some problems that are difficult to write with an imperative approach.
+ </para>
+ <para>
+ The following example is an extension of the "Imperative" example. Pretend that the following Functions exist, and do the following tasks:
+ * getinput : allows the user to enter a number, and returns that number
+ * add : adds together the numbers given as arguments, returning the sum
+ [pre]
+ (
+ postln( add( getinput, getinput ) );
+ )
+ [/pre]
+ </para>
+ <para>
+ SuperCollider will always execute the inner-most Functions first. This is how the interpreter executes the single-line program above:
+ <orderedlist>
+ <listitem><para>Execute the left call of <code>getinput</code></para></listitem>
+ <listitem><para>Execute the right call of <code>getinput</code></para></listitem>
+ <listitem><para>Execute <code>add</code> with the two numbers returned by <code>getinput</code></para></listitem>
+ <listitem><para>Execute <code>postln</code> with the number returned by <code>add</code></para></listitem>
+ </orderedlist>
+ </para>
+ <para>
+ Both imperative and functional programming have advantages and disadvantages. SuperCollider will allow you to use either approach, or a mix of both, when solving problems.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Object_Oriented-Object-Oriented_Programming">
+ <title>Object-Oriented Programming</title>
+ <para>
+ Object-oriented programming is more difficult to think about than imperative or functional. When using this paradigm (mode of thought), almost everything in SuperCollider is thought of as an abstract Object. In this way, it allows programmers to make compelling comparisons to the real world, where all tangible things are objects, and where it is not hard to conceive of most intangible things as objects, too. With object-oriented programming, computer science takes a break from mathematics, and is influenced by philosophy.
+ </para>
+ <para>
+ !!! Include that Classes always start with an upper-case letter !!!
+ </para>
+ <para>
+ Anything can be represented as an Object - like a bicycle, for instance. Let's pretend that we have an Object called a Bicycle. We don't yet have a particular bicycle - just the abstract '''class''' containing everything that is true about all bicycles. If a Bicycle class exists in SuperCollider, you generate a specific instance like this: <code>var bike = Bicycle.new;</code> All SuperCollider Objects can be '''instantiated''' in this way: you get a specific Bicycle from the generic class, and you can then modify and work with your own Object as you choose. The specific properties associated with a particular instance of a class are called '''instance variables'''.
+ </para>
+ <para>
+ There are certain things that Bicycles are designed to do: turn the wheels, turn the handlebar, raise and lower the seat, and so on. You can cause these things to happen by providing a certain input to a real-world Bicycle: if you want to turn the wheels, you might push the pedals. In SuperCollider, you cause things to happen by '''sending a message''' to the Object that tells it what you want: if you have a Bicycle, you might turn the wheels like this: <code>bike.turnTheWheels;</code> When you do this, you are actually executing the <code>turnTheWheels</code> Function, which is defined by the abstract Bicycle class. Because it doesn't make sense to turn the wheels of all bicycles in existence, you don't call the '''method''' (a synonym for "Function") from the Bicycle class itself, but from the particular instance whose wheels you want to turn. The proper way to access instance variables is by using instance methods.
+ </para>
+ <para>
+ If this kind of programming is new to you, it might seem extremely difficult. It can be intimidating at first, but it is actually not too difficult to understand once you start to use it. In fact, you have already been using it! Remember the <code>postln</code> command that was described earlier as a special kind of Function? It's actually a Function defined by SuperCollider's abstract class <code>Object</code>, which defines a set of messages that can be passed to ''any'' SuperCollider Object. Because most things in SuperCollider are Objects, we can send them the <code>postln</code> message, and they will understand that it means to print themselves in the "SuperCollider output" pane.
+ </para>
+ <para>
+ <!-- Begin Confusing??? -->
+ Why is it that all Objects respond to the <code>postln</code> message? SuperCollider classes are allowed to belong to other SuperCollider classes, of which they are a part. Consider the Bicycle class again. It is a kind of vehicle, and philosophers might say that "things that are members of the bicycle class are also members of the vehicle class." That is, real-world bicycles share certain characteristics with other real-world objects that are classified as "vehicles." The bicycle class is a "sub-class" of the vehicle class, and it '''inherits''' certain properties from the vehicles class. SuperCollider allows this behaviour too, and calls it '''inheritance'''. In SuperCollider, since all classes define Objects, they are all automatically considered to be a sub-class of the class called <code>Object</code>. All classes therefore inherit certain characteristics from the <code>Object</code> class, like knowing how to respond to the <code>postln</code> message.
+ <!-- End Confusing??? -->
+ </para>
+ <para>
+ equivalent notation: 5.postln versus postln( 5 )
+ </para>
+ <para>
+ You still don't know how to write new Classes and Objects in SuperCollider, but knowing how to use them is more than enough for now. By the time you need to write your own Classes, you will probably prefer to use the official SuperCollider help files, anyway.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Object_Oriented-Choosing_a_Paradigm">
+ <title>Choosing a Paradigm</title>
+ <para>
+ At this point you may begin worrying about which programming paradigm you should choose, and when. The answer is unhelpful: "Whichever seems best for the task."
+ </para>
+ <para>
+ Let's expand on this. If you are primarily a programmer, then you probably already know how to choose the best paradigm and algorithm for the task. If you are a musician, then you probably just want your program to produce the output that you want (in this case, a particular set of sounds). Part of the beauty of SuperCollider's flexibility is that it allows you to produce the same output in different ways. As a musician this means that, as long as your program works as you want it to work, it doesn't matter how you write it. Experience will teach you more and less effective ways of doing things, but there is no need for rules.
+ </para>
+ <para>
+ Even so, here are some guidelines that will help you to start thinking about music programs:
+ <itemizedlist>
+ <listitem><para>Programs of all sorts often follow a simple, four-step flow. Not all parts are always present.
+ <orderedlist>
+ <listitem><para>Declare variables.</para></listitem>
+ <listitem><para>Get input from the user.</para></listitem>
+ <listitem><para>Calculate something with the input.</para></listitem>
+ <listitem><para>Provide output to the user (i.e. "make noise").</para></listitem>
+ </orderedlist>
+ </para></listitem>
+ <listitem><para>Repetition is the enemy of correctness, so if you're going to execute some code more than once, try writing a Function. If it's slightly different every time, try using arguments. Arguments with default values are a great way to expand a Function's usefulness.</para></listitem>
+ <listitem><para>If it looks too complicated, then it probably is. The more difficult it is to understand something, the greater the chance of making a mistake.</para></listitem>
+ <listitem><para>Don't forget the semicolons at the end of every statement.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ </section> <!-- Ends "Object-Oriented SuperCollider" Section --> <!-- SC-Basic_Programming-Object_Oriented- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Sound_Making_Functions">
+ <title>Sound-Making Functions</title>
+ <para>
+ It's finally time to start thinking about Functions that produce sound!
+ </para>
+ <para>
+ This example is discussed below in the following sections. Remember, when running SuperCollider code in GEdit, you can stop the sound by pressing 'Esc' on your keyboard.
+ [pre]{ SinOsc.ar( 440, 0, 0.2 ); }.play;[/pre]
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Sound_Making_Functions-UGens">
+ <title>UGens</title>
+ <para>
+ "UGen" stands for "unit generator." UGens are special Objects that generate either an audio or a control signal.
+ </para>
+ <para>
+ The UGen that will be used for most of the experimentation in this Guide, and which was primarily used to generate the "Method One" program that goes with this Guide, is called <code>SinOsc</code>, which generates a sine wave. The Class' name, "SinOsc," means "sine oscillator."
+ </para>
+ <para>
+ The example at the beginning of this chapter, <code>SinOsc.ar( 440, 0, 0.2 );</code> produces an "instance" of the <code>SinOsc</code> Class, which continuously outputs a signal, based on the parameters given in parentheses. This instance produces an "audio rate" signal, which means that it is of sufficient quality to eventually become sound.
+ </para>
+ <para>
+ A slightly modified version of that code will give us a "control rate" signal: <code>SinOsc.kr( 440, 0, 0.2 );</code> There is only one small difference between the two examples - for us - but for SuperCollider, the difference is huge. A control rate signal will not be of sufficient quality to become sound; it is used to control other UGens that do become sound.
+ </para>
+ <para>
+ Unlike other Classes, UGen Classes should not be instantiated with the <code>new</code> message. They should always be instantiated as either audio-rate (by passing the <code>ar</code> message), or control-rate (by passing the <code>kr</code> message). Control-rate signals are calculated much less often than audio-rate signals, which allows the SuperCollider interpreter and server to save processing power where it wouldn't be noticed.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Sound_Making_Functions-The_play_Function">
+ <title>The "play" Function</title>
+ <para>
+ The <code>play</code> Function does exactly what it says: it plays its input. The input must be a Function with an audio-rate signal generator as the return value.
+ </para>
+ <para>
+ The following two examples produce the same output:
+ [pre]{ SinOsc.ar( 440, 0, 0.2 ); }.play;[/pre]
+ [pre]play( { SinOsc.ar( 440, 0, 0.2 ); } );[/pre]
+ The first example is written from an object-oriented perspective. Functions know how to play their return value, when passed the <code>play</code> message. This is true of all Functions whose return value is an audio-rate UGen. The second example is written from a functional perspective. The Function called <code>play</code> will play its input, which must be a Function whose return value is an audio-rate UGen. Whether you should write <code>play</code> in the functional or object-oriented way depends on which makes more sense to you.
+ </para>
+ <para>
+ Try to re-write the above example so that the <code>play</code> Function operates on a variable-defined Function.
+ <!--
+ (
+ var noise =
+ {
+ SinOsc.ar( 440, 0, 0.2 );
+ };
+
+ play( noise );
+ noise.play;
+ ) -->
+ </para>
+ <para>
+ The arguments to <code>SinOsc</code>, whether the audio- or control-rate generator, are these:
+ <itemizedlist>
+ <listitem><para>The first is called <code>freq</code>; it sets the frequency.</para></listitem>
+ <listitem><para>The second is called <code>add</code>; it is added to all values produced by the UGen.</para></listitem>
+ <listitem><para>The third is called <code>mul</code>; all values produced by the UGen are multiplied by this.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ You now know enough to spend hours with the sine oscillator UGen. Try combining audio- and control-rate UGens, and try to figure out what happens when each of the arguments is adjusted. Be careful that your audio interface's volume isn't set too high! Experiment with this one:
+ [pre]
+ (
+ var myFrequency = SinOsc.kr( freq:1, mul:200, add:400 );
+ var sound = { SinOsc.ar( myFrequency, 0, 0.2 ); };
+
+ play( sound );
+ )
+ [/pre]
+ WHY DOESN'T THAT WORK?!?!?!?!?!?
+ </para>
+ </section>
+ </section> <!-- Ends "Sound-Making Functions" Section --> <!-- SC-Basic_Programming-Sound_Making_Functions- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Multichannel_Audio">
+ <title>Multichannel Audio</title>
+ <para>
+ By now you must be growing tired of the left-side-only sounds being produced by the examples.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Multichannel_Audio-Stereo_Array">
+ <title>Stereo Array</title>
+ <para>
+ The easiest way to output multichannel audio in SuperCollider is to use a kind of "Collection" (defined later) called an "Array." SuperCollider will theoretically handle any number of audio output channels, but by default is usually only configured for two-channel stereo audio. Since humans have only two ears, this is sufficient for most tasks! A multichannel array is notated like this: <code>[ LeftChannel.ar( x ), RightChannel.ar( y ) ]</code>
+ </para>
+ <para>
+ Here is our simple sine oscillator expanded to produce stereo audio:
+ [pre]{ [ SinOsc.ar( 440, 0, 0.2 ), SinOsc.ar( 440, 0, 0.2 ) ]; }.play;[/pre]
+ Not much has changed, except that the audio we hear is now being emitted from both the left and right channels. Change the frequency of one of the sine oscillators to <code>450</code> and the difference will become much more apparent.
+ </para>
+ <para>
+ Multichannel arrays can also be combined with each other, like this:
+ [pre]
+ {
+ var one = [ x, y, z ];
+ var two = [ a, b, c ];
+ [ one, two ];
+ }
+ [/pre]
+ If <code>a</code>, <code>b</code>, <code>c</code>, <code>x</code>, <code>y</code>, and <code>z</code> were all audio-rate UGens, this Function could be <code>play</code>'ed. It would produce stereo audio, and each channel would have three independent UGens.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Multichannel_Audio-Multichannel_Expansion">
+ <title>Multichannel Expansion</title>
+ <para>
+ You can automatically create multiple UGens by providing an Array as one of the parameters. The SuperCollider interpreter will automatically create multichannel UGens as a result.
+ </para>
+ <para>
+ The following two examples produce equivalent output:
+ [pre]{ [ SinOsc.ar( 440, 0, 0.2 ), SinOsc.ar( 440, 0, 0.2 ) ]; }.play;[/pre]
+ [pre]{ SinOsc.ar( [440, 440], 0, 0.2 ); }.play;[/pre]
+ The second example can be easier to read, because it is obvious that only the frequency is changing - or in this case, that nothing is changing. This technique is more useful in a situation like the following:
+ [pre]{ SinOsc.ar( [[440, 445, 450, 455, 460, 465],
+ [440, 445, 450, 455, 460, 465]],
+ 0,
+ 0.2 ); }.play;[/pre]
+ That's not exactly easy to read, but it's easier to figure out than the most obvious alternative:
+ [pre]{
+ [[ SinOsc.ar( 440, 0, 0.2 ), SinOsc.ar( 445, 0, 0.2 ), SinOsc.ar( 450, 0, 0.2 ), SinOsc.ar( 455, 0, 0.2 ), SinOsc.ar( 460, 0, 0.2 ), SinOsc.ar( 465, 0, 0.2 ) ],
+ [ SinOsc.ar( 440, 0, 0.2 ), SinOsc.ar( 445, 0, 0.2 ), SinOsc.ar( 450, 0, 0.2 ), SinOsc.ar( 455, 0, 0.2 ), SinOsc.ar( 460, 0, 0.2 ), SinOsc.ar( 465, 0, 0.2 ) ]];
+ }.play;[/pre]
+ More importantly, multichannel expansion gives us another tool to avoid repetition. Repetition is the enemy of correctness - it's so much more difficult to find a mistake in the second example than in the first!
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Multichannel_Audio-Method_One">
+ <title>Method One</title>
+ <para>
+ Believe it or not, you now know enough to understand a slightly-modified version of the first part of "Method One," a SuperCollider program written and heavily commented specifically for use with this Guide. You should <code>play</code> this example, and experiment with changing the frequencies, volumes, and so on. The fully-commented version provides a full explanation of how the Function works.
+ [pre]
+ {
+ // sets up the frequencies of both channels
+ var frequencyL = SinOsc.kr( freq:10, mul:200, add:400 ); // oscillating
+ var frequencyR = SinOsc.kr( freq:1, mul:50, add:150 ); // oscillating
+ var frequencyL_drone = SinOsc.kr( freq:0.03, mul:20, add:100 ); // drone
+ var frequencyR_drone = SinOsc.kr( freq:0.01, mul:20, add:210 ); // drone
+
+ // changes the volume of the oscillating part in the left channel
+ var volumeL = SinOsc.kr( freq:0.5, mul:0.02, add:0.03 );
+
+ // left channel
+ var left = [ SinOsc.ar( freq:frequencyL, mul:volumeL ), // this is the oscillating part
+ SinOsc.ar( freq:[frequencyL_drone,2*frequencyL_drone], mul:0.02 ), // the rest make up the drone
+ SinOsc.ar( freq:[5*frequencyL_drone,7*frequencyL_drone], mul:0.005 ),
+ SinOsc.ar( freq:[13*frequencyL_drone,28*frequencyL_drone], mul:0.001 ) ];
+
+ // right channel
+ var right = [ SinOsc.ar( freq:frequencyR, mul:0.1 ), // this is the oscillating part
+ SinOsc.ar( freq:[frequencyR_drone,2*frequencyR_drone], mul:0.02 ), // the rest make up the drone
+ SinOsc.ar( freq:4*frequencyR_drone, mul:0.005 ),
+ SinOsc.ar( freq:[64*frequencyR_drone,128*frequencyR_drone], mul:0.01 ) ]; // high frequencies!
+
+ [ left, right ];
+ }
+ [/pre]
+ </para>
+ </section>
+ </section> <!-- Ends "Multichannel Audio" Section --> <!-- SC-Basic_Programming-Multichannel_Audio- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections">
+ <title>Collections</title>
+ <para>
+ A "collection" is just that - a collection of Objects. Collections are simply a means of organizing a large amount of data, without having to assign a variable name for each portion of data. Compared to other programming languages, SuperCollider provides a relatively large number of Collections in the standard library.
+ </para>
+ <para>
+ We have already seen an example of a Collection as multichannel audio arrays. An Array is a kind of Collection - in object-oriented terminology, the Array Class is a '''sub-class''' of the Collection Class, and inherits its behaviours. Conversely, the Collection Class is the '''super-class''' of the Array Class. The Collection Class itself is not to be used; it is designed to provide common features so that it is easier to write Classes for collections.
+ </para>
+ <para>
+ As with all the chapters from this point on, it is not necessary to read this in sequence. If you prefer, you can skip it and return later when you need to manage a large set of data.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-Array">
+ <title>Array</title>
+ <para>
+ Arrays have been traditionally been very popular with programmers. In SuperCollider, they are capable of storing a large number of Objects, and they provide advanced behaviours that are normally not associated with Arrays. They are not as indespensible as they used to be. Most programming languages now provide (or can easily be extended to add) Lists, Trees, and other kinds of data storage structures, which offer more capabilities, and are easier to use and to think about. Users new to programming might find the various kinds of Lists to be more helpful.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-Array-Building">
+ <title>Building an Array</title>
+ <para>
+ An Array is a Collection with a finite maximum size, determined at declaration time. It is the programmer's responsibility to maintain a meaningful order, and to remember the meaning of the data. Data in an Array is called "elements," each of which is assigned a specific "index number." Index numbers begin at 0. Any mix of Objects can be stored in an Array, including an Array.
+ </para>
+ <para>
+ This example declares an Array, adds some elements, then prints them out.
+ [pre]
+ (
+ var tA = Array.new( 2 ); // "tA" stands for "testArray"
+
+ tA = tA.add( 5 );
+ tA = tA.add( 3 );
+ tA = tA.add( 17 );
+
+ tA.postln;
+ nil;
+ )
+ [/pre]
+ Notice that Array is a Class, and it must be instantiated before use. Here, the variable <code>tA</code> is assigned an Array with enough space for two objects. Notice that the elements are printed out in the order that you add them to the Array. They are not sorted or shuffled (unless you send a message like <code>scramble</code>). But why did I write <code>tA = tA.add( 17 );</code> instead of <code>tA.add( 17 );</code>? Shouldn't the second method be sufficient for adding an Object to an Array, thereby making the re-assignment unnecessary? It does, but let's see what happens when we take it away:
+ [pre]
+ (
+ var tA = Array.new( 2 ); // "tA" stands for "testArray"
+
+ tA.add( 5 );
+ tA.add( 3 );
+ tA.add( 17 );
+
+ tA.postln;
+ nil;
+ )
+ [/pre]
+ The <code>17</code> is missing - it doesn't get added into the Array! This is because the Array was only declared with two slots, and you can't add three Objects into two slots. So why did this work the first time? SuperCollider was programmed to help us fit additional items into an Array. If an Array has reached its capacity, SuperCollider will automatically make a new, larger Array for us, and returns that from the <code>add</code> method. Therefore, any time you add an element to an Array, you should always re-assign the result, so that you don't have to worry about whether you exceeded the Array's capacity.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-Array-Accessing">
+ <title>Accessing an Array's Elements</title>
+ <para>
+ There are two ways to access individual elements within an Array. One way is object-oriented, and one way is more traditional, inspired by programming languages such as the wildly popular "C" language. The object-oriented style uses the <code>at</code> and <code>put</code> methods. The traditional style uses square brackets with an index number.
+ </para>
+ <para>
+ The following examples produce equivalent output. The first uses the object-oriented style, and the second uses the traditional style.
+ [pre]
+ (
+ var tA = Array.new( 3 );
+
+ tA = tA.add( 5 );
+ tA = tA.add( 3 );
+ tA = tA.add( 17 );
+
+ tA.at( 0 ).postln; // outputs 5
+ tA.at( 1 ).postln; // outputs 3
+ tA.at( 2 ).postln; // outputs 17
+
+ tA.put( 0, 24 ); // assigns 24 to element 0
+
+ tA.at( 0 ).postln; // outputs 24
+
+ nil;
+ )
+ [/pre]
+ [pre]
+ (
+ var tA = Array.new( 3 );
+
+ tA = tA.add( 5 );
+ tA = tA.add( 3 );
+ tA = tA.add( 17 );
+
+ tA[0].postln; // outputs 5
+ tA[1].postln; // outputs 3
+ tA[2].postln; // outputs 17
+
+ tA[0] = 24 ; // assigns 24 to element 0
+
+ tA[0].postln; // outputs 24
+
+ nil;
+ )
+ [/pre]
+ Different people prefer different styles of accessing Arrays.
+ </para>
+ </section>
+ </section> <!-- End "Arrays" Section -->
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-List">
+ <title>List</title>
+ <para>
+ An List is a Collection with an infinite maximum size. It is the programmer's responsibility to maintain a meaningful order, and to remember the meaning of the data. Data in a List is called "elements," each of which is assigned a specific "index number." Index numbers begin at 0. Any mix of Objects can be stored in a List, including a List. Lists and Arrays are very similar, but SuperCollider manages some of the dirty work for you, when you use the List Class.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-List-Building">
+ <title>Building a List</title>
+ <para>
+ There are four methods which instantiate a List. These are all "Class methods," meaning they do not operate on a specific List, but can be used to make any List.
+ <itemizedlist>
+ <listitem><para><code>List.new</code> creates a List. You can also specify the initial number of elements as an argument, if you choose.</para></listitem>
+ <listitem><para><code>List.newClear( x )</code> creates a List with x number of slots, filled with <code>nil</code>.</para></listitem>
+ <listitem><para><code>List.copyInstance( aList )</code> creates a List which is a copy of <code>aList</code>.</para></listitem>
+ <listitem><para><code>List.newUsing( anArray )</code> creates a List with the same elements as <code>anArray</code>.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-List-Adding_to_an_Existing_List">
+ <title>Adding to an Existing List</title>
+ <para>
+ These are "instance methods," meaning that they operate on a specific list.
+ <itemizedlist>
+ <listitem><para><code>put( index, item )</code> adds "item" into the List at index number "index".</para></listitem>
+ <listitem><para><code>add( item )</code> adds "item" to the end of a List.</para></listitem>
+ <listitem><para><code>addFirst( item )</code> adds "item" to the beginning of a List.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-List-Accessing">
+ <title>Accessing a List</title>
+ <para>
+ These are "instance methods," meaning that they operate on a specific list.
+ <itemizedlist>
+ <listitem><para><code>at( index )</code> returns the Object assigned to the "index" index number. If "index" is greater than the last element in the List, returns "nil".</para></listitem>
+ <listitem><para><code>clipAt( index )</code> returns the Object assigned to the "index" index number. If "index" is greater than the last element in the List, returns the last element in the List.</para></listitem>
+ <listitem><para><code>wrapAt( index )</code> returns the Object assigned to the "index" index number. If "index" is greater than the last element in the List, returns an element based on a "wrap-around" index number. For a three-element List, 0 will return element 0, 1 returns 1, 2 returns 2, 3 returns 0, 4 returns 1, 5 returns 2, 6 returns 0, and so on.</para></listitem>
+ <listitem><para><code>foldAt( index )</code> returns the Object assigned to the "index" index number. If "index" is greater than the last element in the List, returns an element based on a "fold-back" index number. Whereas <code>wrapAt()</code> will always continue from the lowest to the highest index number, <code>foldAt()</code> will change every time: low to high, high to low, low to high, and so on.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-List-Removing">
+ <title>Removing from a List</title>
+ <para>
+ One way to remove an element from a List is to re-assign that element's index number the value "nil". These two Functions also remove elements from a List. They are "instance methods," meaning that they operate on a specific list.
+ <itemizedlist>
+ <listitem><para><code>pop</code> returns the last element in a List, and removes it from the List.</para></listitem>
+ <listitem><para><code>removeAt( index )</code> removes the element assigned to "index" index number, removing it from the List and shrinking the List. This will not leave a "nil" element in the List.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-List-Examples">
+ <title>Examples</title>
+ <para>
+ The following examples show different ways to use List's.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+
+ tL.add( 42 );
+ tL.add( 820 );
+
+ postln( tL.pop ); // outputs 820
+
+ tL.add( 7 );
+ tL.add( 19 );
+ tL.add( 23 );
+
+ postln( tL.pop ); // outputs 23
+ postln( tL.pop ); // outputs 19
+ postln( tL.pop ); // outputs 7
+ postln( tL.pop ); // outputs 42
+
+ postln( tL.pop ); // List is empty, so we get "nil"
+
+ nil;
+ )
+ [/pre]
+ This code adds numbers to the end of a List, then removes them from the end of the List.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+
+ tL.addFirst( 42 );
+ tL.addFirst( 820 );
+
+ postln( tL.pop ); // outputs 42
+
+ tL.addFirst( 7 );
+ tL.addFirst ( 19 );
+ tL.addFirst ( 23 );
+
+ postln( tL.pop ); // outputs 820
+ postln( tL.pop ); // outputs 7
+ postln( tL.pop ); // outputs 19
+ postln( tL.pop ); // outputs 23
+
+ postln( tL.pop ); // list is empty, so we get "nil"
+
+ nil;
+ )
+ [/pre]
+ This modification of the first example adds numbers to the beginning of a List, then removes them from the end of the List. This is one way to ensure that the List elements are removed in the same order that they are added.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+
+ tL.add( 42 );
+ tL.add( 820 );
+
+ postln( tL.removeAt( 0 ) ); // outputs 42
+
+ tL.add( 7 );
+ tL.add( 19 );
+ tL.add( 23 );
+
+ postln( tL.removeAt( 0 ) ); // outputs 820
+ postln( tL.removeAt( 0 ) ); // outputs 7
+ postln( tL.removeAt( 0 ) ); // outputs 19
+ postln( tL.removeAt( 0 ) ); // outputs 23
+
+ // postln( tL.removeAt( 0 ) ); // would cause an error
+
+ nil;
+ )
+ [/pre]
+ This modification of the first example adds numbers to the end of a List, then removes from the beginning of the List. This is another way to ensure that the List elements are removed in the same order that they're added. Note that, when the List is empty, using the "removeAt()" Function causes an error, because you try to access a List index which doesn't exist.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+
+ tL = [42,820,7,19,23];
+
+ tL.at( 0 ).postln; // outputs 42
+ tL.at( 1 ).postln; // outputs 820
+ tL.at( 2 ).postln; // outputs 7
+ tL.at( 3 ).postln; // outputs 19
+ tL.at( 4 ).postln; // outputs 23
+ tL.at( 5 ).postln; // outputs nil
+ tL.at( 6 ).postln; // outputs nil
+
+ nil;
+ )
+ [/pre]
+ This example shows another way to add elements to an empty List, which also works for Arrays. Then it shows what happens when you try to access elements beyond the end of a List with the "at()"Function.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+
+ tL = [42,820,7,19,23];
+
+ tL.clipAt( 0 ).postln; // outputs 42
+ tL.clipAt( 1 ).postln; // outputs 820
+ tL.clipAt( 2 ).postln; // outputs 7
+ tL.clipAt( 3 ).postln; // outputs 19
+ tL.clipAt( 4 ).postln; // outputs 23
+ tL.clipAt( 5 ).postln; // outputs 23
+ tL.clipAt( 6 ).postln; // outputs 23
+
+ nil;
+ )
+ [/pre]
+ This example shows what happens when you try to access elements beyond the end of a List with the "clipAt()" Function. For index numbers beyond the end of the List, the interpreter will simply return the last element.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+
+ tL = [42,820,7,19,23];
+
+ tL.foldAt( 0 ).postln; // outputs 42
+ tL.foldAt( 1 ).postln; // outputs 820
+ tL.foldAt( 2 ).postln; // outputs 7
+ tL.foldAt( 3 ).postln; // outputs 19
+ tL.foldAt( 4 ).postln; // outputs 23
+ tL.foldAt( 5 ).postln; // outputs 19
+ tL.foldAt( 6 ).postln; // outputs 7
+
+ nil;
+ )
+ [/pre]
+ This example shows what happens when you try to aceess elements beyond the end of a List with the "foldAt()" Function. For index numbers beyond the end of the List, the interpreter will start moving back through the List, towards the first element, "folding" through the List.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+
+ tL = [42,820,7,19,23];
+
+ tL.wrapAt( 0 ).postln; // outputs 42
+ tL.wrapAt( 1 ).postln; // outputs 820
+ tL.wrapAt( 2 ).postln; // outputs 7
+ tL.wrapAt( 3 ).postln; // outputs 19
+ tL.wrapAt( 4 ).postln; // outputs 23
+ tL.wrapAt( 5 ).postln; // outputs 42
+ tL.wrapAt( 6 ).postln; // outputs 820
+
+ nil;
+ )
+ [/pre]
+ This example shows what happens when you try to access elements beyond the end of a List with the "wrapAt()" Function. For index numbers beyond the end of the List, the interpreter will start again at the beginning of the List, "wrapping" around to the beginning.
+ </para>
+ </section>
+ </section> <!-- End "List" Section -->
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-LinkedList">
+ <title>LinkedList</title>
+ <para>
+ Linked lists are very common structures for data management in computer science. They are more efficient than arrays for many tasks, particularly when it's impossible to know how many elements will be required in an array until the program is run. SuperCollider's List Class is implemented with arrays, and it offers nearly the same functionality as the LinkedList class.
+ </para>
+ <para>
+ A true linked list is accessed most efficiently from the start (called the "head" of the list) or the end (called the "tail"). Each element is linked to the one before it, the one after it, or both. SuperCollider's LinkedList Class has elements which are linked both to the preceding and following elements, so it is called a "doubly linked list."
+ </para>
+ <para>
+ Knowing when to use a LinkedList over a List is a question of efficiency, and for small collections of information, it isn't going to make a big difference - you might as well use a basic List. When you plan to store hundreds or thousands of elements, choosing the right Class becomes more important, and can save a lot of processor time. Here is how to know which Class you should use:
+ <itemizedlist>
+ <listitem><para>If you're going to be adding elements to the start or end of the list, and accessing from the start or end of the list, the LinkedList Class will be more efficient.</para></listitem>
+ <listitem><para>If you're going to be adding elements at arbitrary index numbers ''inside'' the list, and accessing elements at arbitrary index numbers inside the list, the List Class will be more efficient.</para></listitem>
+ <listitem><para>If you're going to be adding elements to the start or end, but accessing specific indices, or adding elements at specific indices, but accessing from the start or end, then you get to choose where to save computation time. In one of these cases, it might not matter which one you choose.</para></listitem>
+ </itemizedlist>
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-LinkedList-Inefficient_Functions">
+ <title>Efficient Functions</title>
+ <para>
+ These Functions make use of the LinkedList Class in an efficient way. They are efficient because they access only the first or last element in the LinkedList.
+ <itemizedlist>
+ <listitem><para><code>add( obj )</code> adds "obj" to a LinkedList as the last item.</para></listitem>
+ <listitem><para><code>addFirst( obj )</code> adds "obj" to a LinkedList as the first item.</para></listitem>
+ <listitem><para><code>pop</code> removes the last item in a LinkedList and returns it.</para></listitem>
+ <listitem><para><code>popFirst</code> removes the first item in a LinkedList and returns it.</para></listitem>
+ <listitem><para><code>first</code> returns a copy of the first item in a LinkedList.</para></listitem>
+ <listitem><para><code>last</code> returns a copy of the last item in a LinkedList.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-LinkedList-Efficient_Functions">
+ <title>Inefficient Functions</title>
+ <para>
+ These Functions make use of the LinkedList Class in an inefficient way, but they can be useful. They are inefficient because they may potentially have to review all of the elements in a LinkedList before completing.
+ <itemizedlist>
+ <listitem><para><code>at( index )</code> pretends the LinkedList is an Array, and returns a copy of what would be the element at the given index number.</para></listitem>
+ <listitem><para><code>put( index, obj )</code> pretends the LinkedList is an Array, and changes the element at the given index number to be "obj."</para></listitem>
+ <listitem><para><code>remove( obj )</code> searches through a LinkedList and removes the element judged to be equal to "obj," regardless of its index number.</para></listitem>
+ <listitem><para><code>removeAt( index )</code> pretends the LinkedList is an Array, and removes the element located at the given index number.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-LinkedList-Example">
+ <title>Example</title>
+ <para>
+ This example uses a LinkedList as a queue, adding numbers to the tail, and removing and printing from the head.
+ [pre]
+ (
+ var tL = LinkedList.new;
+
+ tL.add( 42 );
+ tL.add( 89 );
+
+ tL.popFirst.postln; // prints 42
+
+ tL.add( 256 );
+
+ tL.popFirst.postln; // prints 89
+
+ tL.add( 900 );
+
+ tL.popFirst.postln; // prints 256
+ tL.popFirst.postln; // prints 900
+
+ nil;
+ )
+ [/pre]
+ </para>
+ </section>
+ </section> <!-- Ends "LinkedList" Section -->
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Collections-Other_Collections">
+ <title>Other Collections</title>
+ <para>
+ As mentioned previously, the SuperCollider language provides for many more kinds of data structures. The following Collections are useful, but much more complex than those listed above. For usage instructions, refer to the SuperCollider documentation.
+ <itemizedlist>
+ <listitem><para>Dictionary: stores and allows retrieval of data by arbitrary Objects (for example, by symbols, rather than by index numbers).</para></listitem>
+ <listitem><para>Library: a type of Dictionary. Objects inserted can be used by any Object in the program, like books in a real-world library can be used by anybody who walks in.</para></listitem>
+ <listitem><para>Set: an unordered Collection of like Objects, where no two elements are identical.</para></listitem>
+ <listitem><para>SortedList: a List where all elements are kept in a sorted order, regardless of how they are added. The inserted Objects should have a useful ordering method, numerical or lexicographic (alphabetic, for example).</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ </section> <!-- Ends "Collections" Section --> <!-- SC-Basic_Programming-Collections- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Repeating">
+ <title>Repeated Execution</title>
+ <para>
+ Repeating boring tasks is one of the main uses of computers, which don't mind doing the same thing over and over again. More importantly, writing code once and using it many times is much more intelligent than writing the same code many times. Repetition of the same code is often problematic, and repetition with subtle differences is even worse. Errors in this kind of code are difficult to find in the first place, and more difficult to solve effectively. Thankfully, as with most other things, SuperCollider offers a wide variety of ways to repeat code without re-writing it.
+ </para>
+ <para>
+ The code structure used to create repetition is normally called a '''loop'''. "Do" loops are SuperCollider's most versatile and useful repetition structure, and there are a few different ways to think about and write it. The "while" loop is a standard of most programming languages.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Repeating-Simple_Do">
+ <title>"Do This to Everything in This Collection"</title>
+ <para>
+ One way to write a "do" loop is basically the same as telling the interpreter to "do this Function to every element in this Collection." The syntax looks like this,
+ [pre]do( aCollection, aFunction );[/pre]
+ or this,
+ [pre]aCollection.do( aFunction );[/pre]
+ This causes <code>aFunction</code> to be executed once for each element in <code>aCollection</code>, which can be any kind of Collection. Each time <code>aFunction</code> is run, it is given two arguments, in this order: an element of <code>aCollection</code>, and the elements index number. For Collection's that don't have index numbers, it returns what the element's index number would have been. The loop always begins at the start of the Collection, and progresses with each element in order to the end. The second argument, really, is the integers from zero to one less than the number of elements in the Collection, increasing by one each time the loop executes <code>aFunction</code>.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Repeating-Number_Do">
+ <title>"Do This, This Many Times"</title>
+ <para>
+ Another way to write a "do" loop takes advantage of SuperCollider's flexibility, and is really the same as one of the methods above. It's basically equivalent to telling the interpreter to "run this Function this many times." The syntax looks like this,
+ [pre]aNumber.do( aFunction );[/pre]
+ This causes <code>aFunction</code> to be executed <code>aNumber</code> times. The interpreter still provdies two arguments to <code>aFunction</code>, but they are the same: it is the integers from zero to one less than <code>aNumber</code>. You might also think of it as the number of times that <code>aFunction</code> has been executed ''prior'' to this particular execution.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Repeating-Do_Examples">
+ <title>Example "Do" Loops</title>
+ <para>
+ These examples illustrate different ways to use "do" loops for trivial tasks.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+ tL = [27, 46, 102, 81, 34, 0, 39, 26, 203, 62];
+
+ do( tL, { arg item, rep; [rep, item].postln; }; );
+
+ nil;
+ )
+ [/pre]
+ This example is of the first syntax shown. For each element in <code>tL</code>, the interpreter executes the Function once, giving it ''first'' the corresponding element of the Collection, and ''then'' the iteration counter, which happens to be equal to the element's List index number.
+ </para>
+ <para>
+ [pre]
+ (
+ var tL = List.new;
+ var myFunc =
+ {
+ arg item;
+ item.postln;
+ };
+
+ tL = [27, 46, 102, 81, 34, 0, 39, 26, 203, 62];
+
+ tL.do( myFunc; );
+
+ nil;
+ )
+ [/pre]
+ This example does several things differently, but maintains the same basic functionality as the previous example. In this case, the Function only uses the first argument that the interpreter provides, and completely ignores the iteration counter. The syntax here also puts the Collection outside the parentheses, which perhaps makes it more clear that <code>tL</code> is not part of the Function.
+ </para>
+ <para>
+ [pre]
+ (
+ 10.do( { "repeat".postln; }; );
+
+ nil;
+ )
+ [/pre]
+ This example simply prints the string "repeat" ten times. If the Function accepted one argument, it would receive the integers zero through nine. If it accepted two arguments, both of the arguments would be equal.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Repeating-While">
+ <title>"Do This While"</title>
+ <para>
+ "While" loops execute continuously while their "test condition" is evaluated to be "true". Upon reaching the loop, the SuperCollider interpreter executes the test condition. If it is "fale", the interpreter does not execute the loop, and continues with the code after the loop. If it is "true", the interpreter executes the code in the loop once, then re-executes the test condition. If the test condition is "true", the loop is executed, the test condition re-executed, and so on. Until the test condition returns "false", the interpreter will never leave the loop.
+ </para>
+ <para>
+ Here is the format of a "while" loop in SuperCollider:
+ [pre]
+ while( testFunc, bodyFunc );
+ [/pre]
+ or
+ [pre]
+ testFunc.while( bodyFunc );
+ [/pre]
+ The test condition, called <code>testFunc</code>, is a Function which returns a boolean value - either "true" or "false". The loop's body, called <code>bodyFunc</code>, is a Function which can do anything. The loop body function is not provided any arguments by the interpreter. You will have to use comparison operators and boolean expressions when writing the Function for the test condition. For information on how these work in SuperCollider, see !! THIS SECTION HERE !! (#Boolean_Operators and #Boolean_Expressions)?
+ </para>
+ <para>
+ The following three code blocks are equivalent:
+ [pre]
+ (
+ 10.do( { "repeat".postln; }; );
+ )
+ [/pre]
+ and
+ [pre]
+ (
+ var counter = 0;
+ while( { counter < 10; }, { "repeat".postln; counter = counter + 1; } );
+ )
+ [/pre]
+ and
+ [pre]
+ (
+ var counter = 0;
+ { counter < 10; }.while( { "repeat".postln; counter = counter + 1; } );
+ )
+ [/pre]
+ You can see how it's easier to write this particular activity as a "do" loop. It's often the case that a "do" loop better reflects what you want to do, but not always.
+ </para>
+ <para>
+ Contemplate a situation where you are waiting for the user to input some information, which you're going to use to calculate the rest of the composition. The following example isn't real code. It's intended to simplify a complex situation, so you can see where a "while" loop makes more sense than a "do" loop.
+ [pre]
+ play( some background music );
+
+ while( { is the user still inputting information? }, { keep playing music } );
+
+ stop( some background music );
+ [/pre]
+ The background music is begun, and then the interpreter would enter the loop. For as long as the user is still inputting information, the interpreter will then "keep playing music." When the user is not still inputting information, the interpreter will move on to the next command, which stops the music. An equivalent "do" loop would be very difficult to write, if not impossible. This is because we won't know when the user has finished inputting their information until ''after'' they've finished, so we can't plan in advance for how long to play background music.
+ </para>
+ <para>
+ Thus, the most appropriate use of a "while" loop is for cases where you cannot know in advance how many times something should be executed. For most other cases of repeated execution, a "do" loop is the most appropriate choice.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Repeating-">
+ <title>Other Loops</title>
+ <para>
+ The default language provides two other loop structures, both of which are designed to iterate over a series of integer values: "for" loops and "forBy" loops. Their use is more limited than "do" loops. They are explained in the SuperCollider documentation.
+ </para>
+ </section>
+ </section> <!-- Ends "Repeated Execution" Section --> <!-- SC-Basic_Programming-Repeating- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution">
+ <title>Conditional Execution</title>
+ <para>
+ Conditional execution tells the SuperCollider interpreter to execute code on the condition that something is true. SuperCollider offers three conditional execution structures, "if", "switch", and "case" statements. Each of these structures is controlled by one or a series of "boolean expressions" (sometimes called "conditional expressions"), which are composed of "boolean operators".
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Boolean_Operators">
+ <title>Boolean Operators</title>
+ <para>
+ Boolean operators evaluate to "true" or "false", and are most useful in boolean expressions, where they help to determine which portion of a program to execute.
+ </para>
+ <para>
+ The following table lists "binary" boolean operators, meaning that they take two arguments (one on the left and one on the right), and produce either "true" or "false".
+ {|
+ ! Operator !! Meaning
+ |-
+ | < || less than
+ |-
+ | <= || less than or equal to
+ |-
+ | > || greater than
+ |-
+ | >= || greater than or equal to
+ |-
+ | == || equivalent (equal)
+ |-
+ | != || not equivalent (equal)
+ |-
+ | === || identical (the same Object)
+ |-
+ | !== || not identical (not the same Object)
+ |-
+ | && || logical And
+ |-
+ | || || logical Or (two pipe characters... can't be shown in the Wiki table)
+ |}
+ </para>
+ <para>
+ The following table lists "unary" boolean operators, meaning that they take one argument, and work with one of the following syntaxes: <code>argument.operator;</code> or <code>operator( argument );</code>
+ {|
+ ! Operator !! Meaning
+ |-
+ | isPositive || "True" if the argument is greater than or equal to 0
+ |-
+ | isStrictlyPositive || "True" if the argument is greater than 0
+ |-
+ | isNegative || "True" if <code>isPositive</code> is "false"
+ |}
+ </para>
+ <para>
+ The use of these operators is explained below in the "Boolean Expressions" section.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Boolean_Expressions">
+ <title>Boolean Expressions</title>
+ <para>
+ Boolean expressions are expressions which, when executed, result in either "true" or "false". Boolean expressions must use at least one boolean operator (as listed above), or a Function which returns a boolean value. Boolean expressions can also use other operators and Functions.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Simple_Boolean">
+ <title>Simple Expressions</title>
+ <para>
+ Here are a few simple boolean expressions. Of course, variables can be used in place of constant numbers:
+ [pre]
+ 5 < 60; // evaluates to "false"
+ [/pre]
+ [pre]
+ 42 != 42; // evaluates to "false"
+ [/pre]
+ [pre]
+ 42 == 42; // evaluates to "true"
+ [/pre]
+ [pre]
+ 0.isPositive; // evaluates to "true"
+ [/pre]
+ [pre]
+ isNegative( -256 ); // evaluates to "true"
+ [/pre]
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Assignment_and_Equality_Mistake">
+ <title>Assignment/Equality Mistake</title>
+ <para>
+ Beware the following pitfall, common to a large number of programming languages:
+ [pre]
+ a == 42; // evaluates to "true" or "false", depending on the value in "a"
+ [/pre]
+ [pre]
+ a = 42; // assigns the value 42 to "a", over-writing the previously-stored value
+ [/pre]
+ One possible work-around is to write the number first.
+ [pre]
+ 42 == a; // evaluates to "true" or "false", depending on the value in "a"
+ [/pre]
+ [pre]
+ 42 = a; // causes an error, because you can't assign a value to a constant number
+ [/pre]
+ This way, if you accidentally leave out one of the "=" signs, the interpreter will stop execution and produce an error, rather than continuing with an unexpected assignment.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Equality_versus_Identity">
+ <title>Equality versus Identity</title>
+ <para>
+ The identity-equivalence operators are not usually needed.
+ [pre]
+ (
+ var a = [12,24,48];
+ var b = [12,24,48];
+
+ a == b; // evaluates to "true"
+ a === b; // evaluates to "false"
+ )
+ [/pre]
+ The "==" operator evaluates to "true" because "a" and "b" represent equivalent Objects - they are ''equal''. The "===" operator evaluates to "false" because "a" and "b" represent different instances of the Objects - they are not ''identical''.
+ [pre]
+ (
+ var a = [12,24,48];
+ var b = a;
+
+ a == b; // evaluates to "true"
+ a === b; // evaluates to "true"
+ )
+ [/pre]
+ In this case, the "==" operator still evaluates to "true". The "===" operator also evaluates to "true", because "a" and "b" both represent the same Object. When the interpreter evaluates <code>var b = a;</code> in the example above, it actually assigns "b" the same value that "a" stores, not a copy of it.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Logical_And_and_Or">
+ <title>Logical And and Or</title>
+ <para>
+ The logical And and Or operators must receive two boolean arguments. Logical And returns "true" if both of its arguments are "true". Logical Or returns "true" if one of its arguments are "true".
+ </para>
+ <para>
+ The following table illustrates how the SuperCollider interpreter will evaluate each of the following situations.
+ {|
+ ! If the left sub-expression evaluates to... !! ... and the right sub-expression evaluates to... !! ... then logical And would evaluate to... !! ... and logical Or would evaluate to...
+ |-
+ | true || false || false || true
+ |-
+ | false || true || false || true
+ |-
+ | true || true || true || true
+ |-
+ | false || false || false || false
+ |}
+ </para>
+ <para>
+ The interpreter evaluates the expression on the left first, and then the expression on the right ''only'' if it will influence the outcome. This means that, if the left-side expression of a logical Or operator evaluates to "true", the interpreter will not test the right-side expression, because the result will be "true" anyway. Similarly, if the left-side expression of a logical And operator evaluates to "false", the interpreter will not test the right-side expression, because the result will be "false" anyway.
+ </para>
+ <para>
+ This can be exploited to help avoid errors like division-by-zero.
+ [pre]
+ (
+ var x = 5.rand; // assigns a pseudo-random number between 0 and 5
+
+ ( x != 0 ) && ( { x = 17 / x; } ); // doesn't divide by x if it would cause division-by-zero
+
+ x; // the interpreter automatically prints this value after execution
+ )
+ [/pre]
+ If the left-side expression of the logical And operator is "false", the interpreter doesn't evaluate the right-side expression; it simply moves on to the next expression. If the left-side expression is "true" (meaning that x is not zero), then the right-side expression is evaluated. The right-side expression happens to be a Function which assigns "x" the result of dividing 17 by its previous value. The result of the logical And operation is simply discarded in this case - it doesn't really matter to us. This isn't the most straight-forward code, and there are other ways to avoid division-by-zero. If you use this, it's probably best to include a brief explanation of what the code does, as a commment.
+ </para>
+ <para>
+ If you run this code many times, you will see that it gives many different results - one of which is zero, which proves that the code works as intended. If SuperCollider divides by zero, the result is "inf", representing infinity. Try modifying the code so that it will divide by zero, and see what happens.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Order_of_Precedence">
+ <title>Order of Precedence</title>
+ <para>
+ In complicated boolean expressions, it's important to clarify the order in which you want sub-expressions to be executed. This order is called the "order of precedence," or [http://en.wikipedia.org/wiki/Order_of_operations "order of operations."] In computer science, different programming languages enforce different orders of precedence, so you should use parentheses to clarify your intended order, to proactively avoid later confusion. The interpreter will evaluate an expression from left to right, and always fully evaluate parentheses before continuing.
+ </para>
+ <para>
+ Even simple expression can benefit from parentheses. These produce the same results:
+ [pre]
+ (
+ var a = 5 == 5 && 17 != 5;
+ var b = ( 5 == 5 ) && ( 17 != 5 ); // parentheses help to clarify
+
+ a == b; // evaluates to "true"
+ )
+ [/pre]
+ [pre]
+ (
+ var a = 5.isPositive && isNegative( 6 ) || 12 + 5 * 42 - 1 > 18 ;
+ var b = ( 5.isPositive && isNegative( 6 ) ) || ( ((12 + 5) * 42 - 1) > 18 ); // parentheses help to clarify
+
+ a && b; // evaluates to "true"
+ )
+ [/pre]
+ And perhaps even more surprisingly...
+ [pre]
+ ( 12 + 5 * 42 - 1 ) != ( (12 + 5) * 42 - 1 );
+ [/pre]
+ ... evaluates to "false"! They're equal - the interpreter doesn't follow the standard mathematical order of precedence rules! SuperCollider evaluates from left to right, so it's important to clarify to the interpreter what you mean. Where would you put parentheses so that SuperCollider evaluates the expression as per the standard mathematical order of precedence rules, with multiplication before addition and subtraction?
+ </para>
+ </section>
+ </section> <!-- Ends "Boolean Expressions" Section -->
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-If_Statements">
+ <title>"If This Is True, Then... "</title>
+ <para>
+ The "if" structure is provided a boolean expression and two Functions. If the expression evaluates to "true", it executes one Function. If the expression evaluates to "false", it executes the other Function.
+ </para>
+ <para>
+ Here are the two ways to write an "if" structure:
+ [pre]
+ if ( booleanExpression, trueFunction, falseFunction );
+ [/pre]
+ and
+ [pre]
+ booleanExpression.if( trueFunction, falseFunction );
+ [/pre]
+ It's possible to exclude the <code>falseFunction</code>, which is like telling the interpreter, "If the boolean expression is true, then execute this Function. Otherwise, don't execute it."
+ </para>
+ <para>
+ [pre]
+ (
+ var test = [true,false].choose; // pseudo-randomly chooses one of the elements in the List
+
+ if ( ( true == test ), { "It's true!".postln; }, { "It's false!".postln; } );
+ nil;
+ )
+ [/pre]
+ This example prints out a nice message, saying whether <code>test</code> is "true" or "false". Because <code>test</code> is already a boolean value, we don't need to include it in an expression. The "if" statement could have been shortened like this: <code>if ( test, { "It's true!".postln; }, { "It's false!".postln; } );</code>
+ </para>
+ <para>
+ Suppose we only wanted to be alerted if <code>test</code> is "true".
+ [pre]
+ (
+ var test = [true,false].choose; // pseudo-randomly chooses one of the elements in the List
+
+ test.if( { "It's true!".postln; } );
+ nil;
+ )
+ [/pre]
+ In this example, the alternate "if" syntax is used, where the boolean expression is placed before the parentheses.
+ </para>
+ <para>
+ "If" structures can also be "nested," which is like telling the interpreter, "If this is true, do this; otherwise if this is true, do this; otherwise if this is true, do this." In this relatively simple example of nesting, the interpreter evaluates each "if" structure only if the previous one was "false".
+ [pre]
+ (
+ var test = [1,2,3].choose; // pseudo-randomly chooses one of the elements in the List
+
+ if( 1 == test, { "It's one!".postln; },
+ if( 2 == test, { "It's two!".postln; },
+ if( 3 == test, { "It's three!".postln; } ) ) );
+
+ nil;
+ )
+ [/pre]
+ </para>
+ <para>
+ This is a more complex example of nesting:
+ [pre]
+ (
+ var testA = [1,2,3].choose; // pseudo-randomly chooses one of the elements in the List
+ var testB = [1,2,3].choose;
+
+ if( 1 == testA, { ( 1 == testB ).if( { "It's one and one!".postln; },
+ ( 2 == testB ).if( { "It's one and two!".postln; },
+ ( 3 == testB ).if( { "It's one and three!".postln; } ) ) ); },
+ if( 2 == testA, { ( 1 == testB ).if( { "It's two and one!".postln; },
+ ( 2 == testB ).if( { "It's two and two!".postln; },
+ ( 3 == testB ).if( { "It's two and three!".postln; } ) ) ); },
+ if( 3 == testA, { ( 1 == testB ).if( { "It's three and one!".postln; },
+ ( 2 == testB ).if( { "It's three and two!".postln; },
+ ( 3 == testB ).if( { "It's three and three!".postln; } ) ) ); } ) ) );
+
+ nil;
+ )
+ [/pre]
+ As you can see, this type of nesting is not easy to figure out - from the standpoint of the original programmer or somebody else who wishes to use your code. In writing this example, it took me several attempts before getting the parentheses and braces right. Usually, if you have a long list of possibilities to test (like the nine in this example), it is better to use a "case" or "switch" structure. Not only does this help to make the code easier to understand, but the SuperCollider interpreter can apply optimizations that make the code run marginally faster.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Switch_Statements">
+ <title>"Switch Execution to This Path"</title>
+ <para>
+ A "switch" structure can be most easily understood by comparison to a switch in a railway line. As a train approaches a railway switch, an operator inspects the train, and decides whether it should be going to the passenger station, the freight station, or the garage for storage. A "switch" structure - like a railways switch, can only act on one Object at a time, but the Object can be a Collection, allowing you to compare multiple things at once. Each case is tested with the boolean equality operator before being executed.
+ </para>
+ <para>
+ Here is the syntax of a "switch" statement:
+ [pre]
+ case( compareThis,
+ toThis1, { doThis; },
+ toThis2, { doThis; },
+ toThis3, { doThis; }
+ );
+ [/pre]
+ You can include any number of cases. Notice that there is no comma after the last case, and that I've put the concluding ");" on a separate line with the same indentation as the word "case", so that it's easy to see.
+ </para>
+ <para>
+ The following example shows a simple switch.
+ [pre]
+ (
+ var grade = 11.rand + 1; // pseudo-randomly chooses 0 to 11, then adds 1 to give 1 to 12
+
+ grade =
+ switch( grade,
+ 1, { "D-" },
+ 2, { "D" },
+ 3, { "D+" },
+ 4, { "C-" },
+ 5, { "C" },
+ 6, { "C+" },
+ 7, { "B-" },
+ 8, { "B" },
+ 9, { "B+" },
+ 10, { "A-" },
+ 11, { "A" },
+ 12, { "A+" }
+ );
+
+ ("Your grade is" + grade).postln;
+ nil;
+ )
+ [pre]
+ The code picks a pseudo-random number between 1 and 12, then uses a "switch" structure to convert that number into a letter-grade, assigning it to the same <code>grade</code> variable. Then, it adds the "Your grade is" string to the value of <code>grade</code> (with a space between), and prints that result.
+ </para>
+ <para>
+ This example avoids the complex nested "if" structure from above.
+ [pre]
+ (
+ var testA = [1,2,3].choose; // pseudo-randomly chooses one of the elements in the List
+ var testB = [1,2,3].choose;
+
+ switch( [testA,testB],
+ [1,1], { "It's one and one!".postln; },
+ [1,2], { "It's one and two!".postln; },
+ [1,3], { "It's one and three!".postln; },
+ [2,1], { "It's two and one!".postln; },
+ [2,2], { "It's two and two!".postln; },
+ [2,3], { "It's two and thre!".postln; },
+ [3,1], { "It's three and one!".postln; },
+ [3,2], { "It's three and two!".postln; },
+ [3,3], { "It's three and three!".postln; }
+ );
+
+ nil;
+ )
+ [/pre]
+ This is an elegant way to inspect two otherwise-separate variables. Remember that the first argument to "switch" (in this case, it's <code>[testA,tesB]</code>) is compared to the first argument of possibe result with the equality operator: "==".
+ </para>
+ <para>
+ When evaluating which switch to use, the SuperCollider interpreter will always apply the ''last'' one that evaluates to "true".
+ [pre]
+ (
+ switch( 5,
+ 5, { "one".postln; },
+ 5, { "two".postln; },
+ 5, { "three".postln; }
+ );
+
+ nil;
+ )
+ [/pre]
+ All of these cases are true, but this will always result in "three" being printed.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Conditional_Execution-Case_Statements">
+ <title>"In This Case, Do This"</title>
+ <para>
+ "Case" and "switch" structures look similar, but work in subtly different way. A "switch" structure is like a railway switch, allowing one train to be routed onto the right track, according to qualities of the train. A "case" structure, on the other hand, works like somebody trying to decide how to get to work. The person might ask themselves how far they are going, how long they have to get to work, how fast the available options are, what the available options cost, and so on. While in a "switch" structure, the path of execution is determined by examining only one Object, a "case" structure determines the path of execution based on any number of things.
+ </para>
+ <para>
+ Here is the syntax of a "case" structure:
+ [pre]
+ case
+ booleanFunction resultFunction
+ booleanFunction resultFunction
+ booleanFunction resultFunction
+ booleanFunction resultFunction
+ ;
+ [/pre]
+ </para>
+ <para>
+ Contemplate the following pseudo-code example, which represents a possible musical sitation, and a good use of the "case" structure.
+ [pre]
+ (
+ var coolFunction =
+ {
+ case
+ { is there no music playing?
+ AND people are in the room } { play music }
+ { has the same song been playing for too long?
+ OR is the song boring? } { change the song }
+ { has everybody left the room? } { turn off the music }
+ { has a song been requested? } { change to that song }
+ { is the music too loud? } { lower the music's volume }
+ { is the music too quiet? } { raise the music's volume }
+ { is the music too fast? } { lower the music's tempo }
+ { is the music too slow? } { raise the music's tempo }
+ { is everything okay? } { wait for 10 seconds }
+ ;
+ };
+
+ ( 5 == 5 ).while( coolFunction ); // executes coolFunction contiuously
+ )
+ [/pre]
+ It might seem like this example doesn't relate to a real SuperCollider programming situation, but in fact it might. If you could program Function's which determined all of those questions and all of the answers, this sort of "case" structure would be very helpful in a situation where a computer running SuperCollider were left in a room by itself, and expected to play music whenever anybody entered the room. Since five is always equal to five, the interpreter will run <code>coolFunction</code> forever. If the music needs adjustment in some way, the Function will adjust the music. If everything is okay, then the interpreter will wait for 10 seconds, and then the loop will cause the Function to be re-evaluated. Because many different criteria are evaluated in the "case" structure, this represents an efficient use of the structure.
+ </para>
+ <para>
+ "Case" structures can be used to do the same thing as "switch" structures, but it's usually less elegant solution. Also, it doesn't allow the interpreter to use an speed optimization that it would have used in an equivalent "switch" structure.
+ [pre]
+ (
+ var grade = 11.rand + 1; // pseudo-randomly chooses 0 to 11, then adds 1 to give 1 to 12
+
+ grade =
+ case
+ { 1 == grade; } { "D-" }
+ { 2 == grade; } { "D" }
+ { 3 == grade; } { "D+" }
+ { 4 == grade; } { "C-" }
+ { 5 == grade; } { "C" }
+ { 6 == grade; } { "C+" }
+ { 7 == grade; } { "B-" }
+ { 8 == grade; } { "B" }
+ { 9 == grade; } { "B+" }
+ { 10 == grade; } { "A-" }
+ { 11 == grade; } { "A" }
+ { 12 == grade; } { "A+" }
+ ;
+
+ ("Your grade is" + grade).postln;
+ nil;
+ )
+ [/pre]
+ This example is equivalent to one of the "switch" structure examples. This is not a good use of the "case" structure, because it requires a lot of code repetition.
+ </para>
+ <para>
+ Unlike a "switch" structure, a "case" structure will always follow the ''first'' case that evaluates to "true".
+ [pre]
+ (
+ case
+ { 5 == 5; } { "one".postln; }
+ { 5 == 5; } { "two".postln; }
+ { 5 == 5; } { "three".postln; }
+ ;
+
+ nil;
+ )
+ [/pre]
+ This example will always result in "one" being printed.
+ </para>
+ </section>
+ </section> <!-- Ends "Conditional Execution" Section --> <!-- SC-Basic_Programming-Conditional_Execution- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Combining_and_Mix">
+ <title>Combining Audio; the Mix Class</title>
+ <para>
+ One of the requirements of multi-channel audio is the ability to combine a large number of UGen's into a small number of channels - normally just two. The SuperCollider interpreter allows you to accomplish this in a number of ways, which are explained here.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Combining_and_Mix-Mix_Class">
+ <title>The "Mix" Class</title>
+ <para>
+ The "Mix" Class allows you to combine a mutli-channel Array into one channel. It's just that simple: you put in an Array of UGens, and out comes a single-channel combination of them.
+ </para>
+ <para>
+ Here are the two possible syntaxes for the "Mix" Class:
+ [pre]
+ Mix.new( ArrayOfUGens );
+ [/pre]
+ and
+ [pre]
+ Mix( ArrayOfUGens );
+ [/pre]
+ The second form is simply a short-hand version of the first. The "Mix" Class doesn't really create "Mix" Objects either - it's just a Function that combines many UGen's into one.
+ </para>
+ <para>
+ Here's an example of the "Mix" Class in action:
+ [pre]
+ {
+ Mix( [SinOsc.ar(220, 0, 0.1),
+ SinOsc.ar(440, 0, 0.1),
+ SinOsc.ar(660, 0, 0.1),
+ SinOsc.ar(880, 0, 0.1),
+ SinOsc.ar(850, 0, 0.1),
+ SinOsc.ar(870, 0, 0.1),
+ SinOsc.ar(880, 0, 0.1),
+ SinOsc.ar(885, 0, 0.1),
+ SinOsc.ar(890, 0, 0.1),
+ SinOsc.ar(1000, 0, 0.1)] );
+ }.play;
+ [/pre]
+ Notice how all of these SinOsc's are heard through the left channel only. The "Mix" Class mixes all the UGen's together into one. You could use a bus to send the audio to both the left and right channels. What happens if we don't use the Mix Class? Try removing the Function, and find out. You only hear some of the SinOsc's. Which ones? The first two, representing the left and right channels. If your audio interface has more than two channels, you may be able to hear more than those first two channels.
+ </para>
+ <para>
+ There is another Function offered by the Mix Class, and it is a kind of loop. The Function is called <code>Fill</code>, and it takes two arguments: the number of times to run a Function, and the Function to run. The Function is provided with one argument (like in a "do" loop), which is the number of times the Function has ''already'' been run.
+ [pre]
+ (
+ var n = 8;
+ var sineFunc =
+ {
+ arg iteration;
+
+ var freq = 440 + iteration;
+ SinOsc.ar( freq:freq, mul:1/n );
+ };
+
+ { Mix.fill( n, sineFunc ); }.play;
+ )
+ [/pre]
+ As you can see, the "fill" Function itself is quite simple: you provide the number of UGen's to create, and a Function that creates UGen's. It's the <code>sineFunc</code> Function that is a little confusing. The argument is called "iteration", because it holds how many times the Function has already been run - how many iterations have happened already. It uses this value to help calculate the frequency (stored in a variable called "freq"), and then creates a SinOsc UGen. The "mul" argument helps to automatically control the volume level. Since the total volume should be no more than 1.0, the "sineFunc" Function calculates UGen's' volume by dividing 1, the maximum level, by the number of UGen's that will be created. The slowly pulsating volume is part of the acoustic result of this many frequencies being so close together - it is not a hidden effect by SuperCollider.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Combining_and_Mix-Arrays_of_Arrays">
+ <title>Arrays of Arrays</title>
+ <para>
+ There is another way to combine many UGen's into two channels for stereo output: rather than sending the Array's to the Mix class, combine them into a two-element Array.
+ </para>
+ <para>
+ [pre]
+ {
+ [
+ [ SinOsc.ar(440, 0, 0.1), SinOsc.ar( 880, 0, 0.1 ), SinOsc.ar( 1660, 0, 0.1 ) ],
+ [ SinOsc.ar(440, 0, 0.1), SinOsc.ar( 880, 0, 0.1 ), SinOsc.ar( 1660, 0, 0.1 ) ]
+ ];
+ }.play;
+ [/pre]
+ Here, a two-element Array is the result of a Function, which gets sent the "play" message. Each of the elements is an equivalent, three-element Array where each element is a UGen.
+ </para>
+ <para>
+ This representation also offers another benefit: each UGen can have a different "mul" value, which will be preserved.
+ [pre]
+ {
+ [
+ [ SinOsc.ar(440, 0, 0.2), SinOsc.ar( 880, 0, 0.1 ), SinOsc.ar( 1660, 0, 0.05 ) ],
+ [ SinOsc.ar(440, 0, 0.2), SinOsc.ar( 880, 0, 0.1 ), SinOsc.ar( 1660, 0, 0.05 ) ]
+ ];
+ }.play;
+ [/pre]
+ This sounds much less harsh than the first example. Try it with the Mix Class. Even with the different "mul" values, it sounds the same as the first example! This helps Mix to ensure that the total level doesn't exceed 1.0, but it has the disadvantage that careful level-balancing on your part will be erased.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Combining_and_Mix-Addition">
+ <title>Addition</title>
+ <para>
+ This method of combinine UGen's into two channels uses the addition operator: +
+ </para>
+ <para>
+ [pre]
+ {
+ [
+ ( SinOsc.ar(440, 0, 0.1) + SinOsc.ar( 880, 0, 0.1 ) + SinOsc.ar( 1660, 0, 0.1 ) ),
+ ( SinOsc.ar(440, 0, 0.1) + SinOsc.ar( 880, 0, 0.1 ) + SinOsc.ar( 1660, 0, 0.1 ) )
+ ];
+ }.play;
+ [/pre]
+ Notice that, like with the Mix Class, independent "mul" levels are not preserved.
+ </para>
+ </section>
+ </section> <!-- Ends "Combining Audio; the Mix Class" Section --> <!-- SC-Basic_Programming-Combining_and_Mix- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth">
+ <title>SynthDef and Synth</title>
+ <para>
+ The preceding sections of this "Basic Programming" guide have only created sound with Function's. The truth is that Function's are very useful for creating sound, but they represent a simplification of the actual commands and Functions that must be run by the interpreter in order to create sound.
+ [pre]
+ // When you write this...
+ (
+ { SinOsc.ar( freq:440, mul:0.2 ); }.play;
+ )
+
+ // The interpreter actually does this...
+ (
+ SynthDef.new( "temp__963", { Out.ar( 0, SinOsc.ar( freq:440, mul:0.2 ) ); } ).play;
+ )
+ [/pre]
+ Yikes! Don't despair - it's easy to understand - it just looks scary!
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Out_UGen">
+ <title>"Out" UGen</title>
+ <para>
+ The "Out" UGen is one of the bits of magic automatically taken care of by the interpreter. It routes an audio signal from another UGen into a specific output (actually, into a specific bus - explained in the !! BUSSES !! section).
+ </para>
+ <para>
+ The following examples have the same effect:
+ [pre]
+ { SinOsc.ar( freq:500, mul:0.2 ); }.play;
+ [/pre]
+ and
+ [pre]
+ { Out.ar( 0, SinOsc.ar( freq:500, mul:0.2 ) ); }.play;
+ [/pre]
+ The first argument to "Out.ar" is the bus number for where you want to place the second argument, which is either a UGen or a multi-channel Array of UGen's. If the second argument is an Array, then the first element is sent to the first argument's bus number, the second argument is sent to one bus number higher, the third to two bus numbers higher, and so on. This issues is explained fully in the !! BUSSES !! section, but here's what you need to know for now, working with stereo (two-channel) audio:
+ <itemizedlist>
+ <listitem><para>If the second argument is a two-element Array, use bus number 0.</para></listitem>
+ <listitem><para>If the second argument is a single UGen, and you want it to be heard through the left channel, use bus number 0.</para></listitem>
+ <listitem><para>If the second argument is a single UGen, and you want it to be heard through the right channel, use bus number 1.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ If you're still struggling with exactly what the "Out" UGen does, think of it like this: when you create an audio-rate UGen, it starts creating an audio signal; the "Out" UGen effectively connects the audio-rate UGen into your audio interface's output port, so it can be heard through the speakers. In the !! BUSSES !! section, it becomes clear that there are, in fact, other useful places to connect an audio-rate UGen (through an effect processor, for example), and the "Out" UGen can help you do that.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-SynthDef">
+ <title>SynthDef</title>
+ <para>
+ A SynthDef is what we use to tell the server how to create sound. In order to truly understand what SynthDef accomplishes, we need to recall the disconnect between the interpreter and the server. In reality, the interpreter has no idea how to make sound or work with audio hardware. The server, likewise, has no understanding at all of the SuperCollider language. The interpreter takes the code that we write, and does one of a number of things, depending on the nature of the code:
+ <itemizedlist>
+ <listitem><para>executes it completely,</para></listitem>
+ <listitem><para>executes it partially, makes choices, and then does something else</para></listitem>
+ <listitem><para>send the server information about how to synthesize sound,</para></listitem>
+ <listitem><para>etc.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ For simple code like <code>2.postln;</code> the interpreter just executes it. For code like <code>{ SincOsc.ar; }.play;</code> the interpreter expands it a bit, then sends instructions to the server, which deals with the rest of the synthesis process.
+ </para>
+ <para>
+ A SynthDef is part of this last process; SynthDef Objects represent the synthesis information that is sent to the server before (or at the same time as) telling the server to play the sound.
+ </para>
+ <para>
+ There are two steps to creating a useful SynthDef: making an interpreter Object, and sending the actual synthesis information to the server. There are two ways to write this, as follows:
+ [pre]
+ someVariable = SynthDef.new( nameOfSynthDef, FunctionContainingOutUGen );
+ someVariable.send( nameOfServer );
+ [/pre]
+ and
+ [pre]
+ SynthDef.new( nameOfSynthDef, FunctionContainingOutUGen ).send( nameOfServer );
+ [/pre]
+ The <code>FunctionContainingOutUGen</code> is simply that - a Function that, when executed, returns an "Out" UGen (meaning that the "Out" UGen must be the last expression in the Function). The <code>nameOfSynthDef</code> should be a symbol (described !!BELOW!!), but can also be a string. The <code>nameOfServer</code> is a variable that represents the server to which you want to send the SynthDef's information; unless you know that you need to use a different variable for this, it's probably just the letter "s", which the interpreter automatically assigns to the default server.
+ </para>
+ <para>
+ Here is a demonstration of both methods:
+ [pre]
+ (
+ var playMe =
+ {
+ Out.ar( 0, SinOsc.ar( freq:440, mul:0.2 ) );
+ };
+
+ var playMeSynthDef = SynthDef.new( \playMe, playMe );
+
+ playMeSynthDef.send( s );
+
+ nil;
+ )
+ [/pre]
+ and
+ [pre]
+ (
+ var playMe =
+ {
+ Out.ar( 0, SinOsc.ar( freq:440, mul:0.2 ) );
+ };
+
+ SynthDef.new( \playMe, playMe ).send( s );
+
+ nil;
+ )
+ [/pre]
+ The only advantage to assigning something to a variable is the ability to refer to it later. If you use the first method, then you can send the SynthDef to more than one server. Since it's rare that you will want to use more than one server, it's usually better to use the second style. In fact, if you won't be using the "playMe" Function again, you don't need to assign it to a variable!
+ [pre]
+ SynthDef.new( \playMe, { Out.ar( 0, SinOsc.ar( freq:440, mul:0.2 ) ); } ).send( s );
+ [/pre]
+ This is all that's really needed to create and send a synthesis definition to the server. It looks long and frightening, but now at least you understand what all of the parts do.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Load">
+ <title>Load</title>
+ <para>
+ There is another way to send a SynthDef to the server: the "load" Function. The "send" Function sends the synthesis information to the server, which stores it in memory. When the server stops running, all synthesis information given with "send" is lost. The "load" Function, on the other hand, sends the synthesis information to the server, which stores it on disk and in memory. Every time the server is started, it loads all of the synthesis information previously sent to it with the "load" Function. The definition remains until you delete it specifically. This is most useful for a SynthDef that takes up a lot of memory, and which would use considerable network time to transfer to the server whenever the server is run. It is also useful to use the "load" Function instead of "send", when there are a lot of SynthDef's, regardless of the size of each one. The idea is the same: avoid sending the SynthDef in order to save time.
+ </para>
+ <para>
+ The syntax and usage for "load" is the same as for "send".
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Symbols">
+ <title>Symbols</title>
+ <para>
+ As stated in the section about variables, a symbol is simply something which represents something else. When used in the context of a SynthDef, a symbol is a string of characters that refers to a SynthDef that we've already sent to the server. What wasn't mentioned in the section about variables is that, in addition to the symbols that can be used as variable names, the SuperCollider language provides a distinct data-type (like numbers or strings) for symbols. Many programming languages don't provide a "symbol" data-type, so many programmers do not use them extensively, but they are very handy for situations like this. As local variable names are symbols representing data stored by the interpreter, here we are using the symbol data-type to refer to data stored on the server.
+ </para>
+ <para>
+ Symbols are a better way to name SynthDef's than strings. Not only do symbols take up less memory, they aren't actually the interpreter doesn't actually think of them as Objects, and neither should you. Symbols are universally unique; only one instance of a symbol with the same characters can exist. On the other hand, an infinite number of strings with the same characters can exist. When we use a symbol, we are defining it universally. When we use a string, the server pretends that all strings with the same characters are the same philosophical object, even though they aren't. This isn't a technical problem, but it can be difficult to think about, and is cognitively dissonant.
+ </para>
+ <para>
+ If all this seems a little abstract and ontological, that's because it is.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Easy_Symbols">
+ <title>Symbols: the Easy Way</title>
+ <para>
+ Symbols are things that you should use to identify a SynthDef sent to the server.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Writing_Symbols">
+ <title>Writing Symbols</title>
+ <para>
+ There are two ways to write out a symbol: between single-quotation marks, and after a back-slash. Symbols given between single-quotation marks can contain any characters but a single-quotation mark. Symbols given after a back-slash can contain any characters but a space. Neither type of symbol name can cross onto a new line.
+ </para>
+ <para>
+ The following example contains some valid symbols, and some invalid symbols.
+ [pre]
+ \stopSign \\ this is a symbol
+ \stop sign \\ this is a symbol called 'stop' followed by the unrelated word 'sign'
+ 'stopSign' \\ this is a symbol
+ 'stop sign' \\ this is a symbol
+ 'stop
+ sign' \\ these lines are not a symbol, and will cause an error
+ [/pre]
+ </para>
+ <para>
+ The following example illustrates the differences between strings and symbols.
+ [pre]
+ var a = "stop sign" \\ a string
+ var b = "stop sign" \\ a string with the same letters as the first string
+ a == b; \\ returns "true" because the strings are equivalent
+ a === b; \\ returns "false" because the strings are separate copies with the same characters
+ </para>
+ <para>
+ var c = 'stop sign' \\ a symbol
+ var d = 'stop sign' \\ the same symbol
+ c == d; \\ returns "true" because the symbols are equivalent
+ c === d; \\ returns "true" because the symbols are identical
+ [/pre]
+ </para>
+ </section>
+ </section> <!-- Ends "Symbols" Section -->
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-SynthDef_Becomes_Synth">
+ <title>SynthDef Becomes Synth</title>
+ <para>
+ After you send a SynthDef to the server, you can put it into action. When the interpreter tells the server to play a synthesis definition (which the interpreter holds in a SynthDef Object), the server creates a synth from the definition, and starts generating sound. The interpreter gives us a Synth Object to represent each synth on the server, so that we can control the synth.
+ </para>
+ <para>
+ This is the syntax used to create a new synth, after its definition has been sent to the server.
+ [pre]
+ Synth.new( nameOfSynthDef );
+ [/pre]
+ The name will be a symbol or a string - whatever you supplied when you ran the <code>SynthDef.new()</code> Function.
+ </para>
+ <para>
+ Because we're creating a new Synth Object, we should assign it to a variable, for later reference.
+ [pre]
+ SynthDef.new( \playMe, { Out.ar( 0, SinOsc.ar( freq:440, mul:0.2 ) ); } ).send( s );
+ var mySynth = Synth.new( \playMe );
+ [/pre]
+ </para>
+ <para>
+ Recall that the interpreter automatically uses the Synth and SynthDef Classes when we send the "play" message to a Function. We can actually capture and use the Synth Object created from "play-ing" a Function, too. This example is almost the same as the previous one.
+ [pre]
+ var mySynth = { SinOsc.ar( freq:443, mul:0.2 ); }.play;
+ [/pre]
+ The difference is subtle: after the second example, we have no control over what name the interpreter gives to the SynthDef that it sends to the server, so we can't re-use the SynthDef. On the other hand, because we assign the name <code>\sillyTutorialSD</code> to the SynthDef in the first example, we know what it's called, and we can re-use it. Theoretically, we can make an infinite number of synths from this single definition. Realistically, it's limited by the amount of memory the server can use; for most modern computers, this number is so high that we don't ever need to worry about it.
+ </para>
+ <para>
+ As usual, the interpreter provides us with an optional short-cut:
+ [pre]
+ var mySynth = SynthDef.new( \playMe, { Out.ar( 0, SinOsc.ar( freq:440, mul:0.2 ) ); } ).play;
+ [/pre]
+ This automatically sends the synthesis information to the server, creates a synth, and plays it. What minor functionality is lost when we use this shortcut?
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Shortcomings_of_a_SynthDef">
+ <title>Shortcomings of a SynthDef</title>
+ <para>
+ Consider the following program:
+ [pre]
+ (
+ var myRandFunc =
+ {
+ var frequency = 440.rand + 440; // produces an integer between 440 and 880
+ SinOsc.ar( freq:frequency, mul:0.025 );
+ };
+
+ 10.do( { myRandFunc.play; } );
+ )
+ [/pre]
+ Execute the program a few times. The result will be different each time: ten different SinOsc's with ten different frequencies.
+ </para>
+ <para>
+ What if we convert the program to use a SynthDef and multiple Synth's instead? This program will probably cause an error the first time - this is exaplained below.
+ [pre]
+ (
+ var myRandFunc =
+ {
+ var frequency = 440.rand + 440; // produces an integer between 440 and 880
+ Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.025 ) );
+ };
+
+ SynthDef.new( \myRandFunc, myRandFunc ).send( s );
+
+ 10.do( { Synth.new( \myRandFunc ); } );
+ )
+ [/pre]
+ Execute the program a few times. The result is still different each time, but it's the ''same'' ten SinOsc's, all with the same frequency. This is the nature of a SynthDef: once it's sent to the server, you can create a synth from the same instructions without re-sending them.
+ </para>
+ <para>
+ This program causes an error the first time you run it. Inspect the error messages, and see if you can determine why. It's because the server is processing commands ''asynchronously'': things don't happen right when the interpreter asks, but very shortly thereafter. The result is that the server is asked to make a new synth before it deals with the synth definition. There are ways to get around this, but they're too complex for this section - for now (to simplify this text's examples), just accept that the error may happen the first time you run a Synth.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Creating_Change_Anyway">
+ <title>Creating Change Anyway</title>
+ <para>
+ The way to create change and pseudo-randomness anyway is to incorporate another UGen to do it for you. Remember: when you send synthesis information to the server, that information can't change unless you replace it. This doesn't mean that the output produced by the synth can't change!
+ </para>
+ <para>
+ The way to do this is with control-rate UGen's. The following example uses a control-rate SinOsc to set the frequency of an audio-rate SinOsc.
+ [pre]
+ (
+ var myRandFunc =
+ {
+ var frequency = SinOsc.kr( freq:0.5, add:660, mul:220 ); // oscillates between 440 and 880, hitting each extreme every 2 seconds
+ Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.2 ) );
+ };
+
+ SynthDef.new( \myRandFunc, myRandFunc ).send( s );
+
+ Synth.new( \myRandFunc );
+ )
+ [/pre]
+ When you use a UGen as a control-rate UGen, you have to think about its arguments quite differently than when using it as an audio-rate UGen. This table shows how the same argument gives a different result for an audio-rate vs. control-rate UGen used for pitch:
+ {|
+ ! parameter !! audio-rate UGen !! control-rate UGen for pitch
+ |-
+ freq (frequency in Hertz) || controls pitch || controls the speed of oscillation
+ |-
+ add || ?? || re-sets the "zero" (middle) point of the sine wave by adding this to the output
+ |-
+ mul || controls volume level || sets the deviation from the "zero" point
+ |}
+ For an audio-rate SinOsc UGen, you set the frequency and the volume level. For a control-rate UGen, you set the mid-point of oscillation with "add", the extremes of oscillation which will be <code>add - mul</code> and <code>add + mul</code>, and the speed of oscillation with "freq". The end result is very different numbers.
+ </para>
+ <para>
+ There is a handy UGen designed specifically for replacing pseudo-randomness in Functions. The following example restores the "ten different pitches" to the example from the last section.
+ [pre]
+ (
+ var myRandFunc =
+ {
+ var frequency = Rand( 440, 880 ); // produces an integer between 440 and 880
+ Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.025 ) );
+ };
+
+ SynthDef.new( \myRandFunc, myRandFunc ).send( s );
+
+ 10.do( { Synth.new( \myRandFunc ); } );
+ )
+ [/pre]
+ If you run this multiple times, you will again hear ten different pitches. Depending on audio hardware, previous musical experience, and other factors, some people may have difficulty hearing that the pitches are different. Try reducing the number of synths created in the loop.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-SynthDef_with_Arguments">
+ <title>SynthDef with Arguments</title>
+ <para>
+ There are some siutations where you simply cannot pre-determine all of the material that you're going to use when creating a synth. It might be easier to resort to using a Function rather than a SynthDef, but there is yet another solution - creating an argument in your SynthDef Function.
+ </para>
+ <para>
+ With only a subtle change to our Function, we can add the possibility of passing arguments on synth creation:
+ [pre]
+ var myRandFunc =
+ {
+ arg frequency = Rand( 440, 880 ); // default value between 440 and 880
+ Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.025 ) );
+ };
+ [/pre]
+ I've decided to use the Rand UGen anyway, so that supplying a frequency is optional. This adds functionality while making the added complexity optional:
+ [pre]
+ (
+ var myRandFunc =
+ {
+ arg frequency = 440;
+ Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.025 ) );
+ };
+
+ SynthDef.new( \myRandFunc, myRandFunc ).send( s );
+
+ 10.do( { Synth.new( \myRandFunc ); } );
+ )
+ [/pre]
+ If you use the SynthDef in the old way, as in the example, you'll get the expected result: ten Synth's, all with the same frequency. But, if you add a "rand" Function call into the loop, you can get ten different frequencies!
+ [pre]
+ (
+ var myRandFunc =
+ {
+ arg frequency = 440;
+ Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.025 ) );
+ };
+
+ SynthDef.new( \myRandFunc, myRandFunc ).send( s );
+
+ 10.do( { Synth.new( \myRandFunc, [\frequency,(440.rand + 440)] ); } );
+ )
+ [/pre]
+ Notice how we supply arguments: an Array with elements alternating between a string-quoted parameter name, and the value of the argument itself. If we "parameterized" all three main fields of the SinOsc, we could supply them like this:
+ [pre]
+ Synth.new( \mySinOsc, [\freq,440,\add,0,\mul,0.2] );
+ [/pre]
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-SynthDef_and_Synth-Set_and_Free">
+ <title>Things to Do with a SynthDef: Set and Free</title>
+ <para>
+ Once you send a synth definition to the server, and make some synths, you've collected a few Synth Objects, and you wonder what to do with them next. Of course, you could listen to them, but you can also change the arguments that you used, and stop it.
+ </para>
+ <para>
+ To change the arguments used by a synth, send it the "set" message, with a list of arguments:
+ [pre]
+ variableHoldingSynth.set( [\argument1,value,\argument2,value,...] );
+ [/pre]
+ This helps to save even more time and memory: rather than destroying and creating synths all the time, you can simply change pre-existing ones.
+ </para>
+ <para>
+ This modification of the ten-pseudo-random-tones example includes an extra line that lets you change the tones without destroying and re-creating the synths.
+ [pre]
+ // run this first
+ h = List.new;
+
+ // run this second
+ (
+ var myRandFunc =
+ {
+ arg frequency = 440;
+ Out.ar( 0, SinOsc.ar( freq:frequency, mul:0.025 ) );
+ };
+
+ SynthDef.new( \myRandFunc, myRandFunc ).send( s );
+ )
+
+ // run this third
+ 10.do( { h.add( Synth.new( \myRandFunc, [\frequency,(440.rand + 440)] ) ); } );
+
+ // run this fourth, as many times as you please
+ h.do( { arg item; item.set( \frequency, (440.rand + 440) ); } );
+ [/pre]
+ The reason that you have to run each of those segments separately is two-fold: we need to store the List of Synth's in a single-letter variable because, for this simple demonstration, this is the most efficient way; second, for the asynchronous behaviour of the server that was previously noted as causing an error.
+ </para>
+ <para>
+ The only aspect of that example that's a little tricky to understand is the "do" loop. Remember that when you run a "do" loop on a List, the interpreter automatically loops over each of the elements in the List, running the Function that you provide. Each time the Function is run, it receives the current List item, and its index number in the List, in that order. So the Function in this loop simply uses "set" to change the "frequency" argument.
+ </para>
+ <para>
+ Take special note that the arguments in this case are not identical to those given with the "new" message. Compare the two forms below:
+ [pre]
+ SynthDef.new( \SynthName, [\parameter1,value,\parameter2,value] );
+ [/pre]
+ and
+ [pre]
+ existingSynth.set( \parameter1, value, \parmeter2, value );
+ [/pre]
+ </para>
+ <para>
+ To get rid of one synth without stopping all sound, send its corresponding Synth the "free" message:
+ [pre]
+ variableHoldingSynth.free;
+ [/pre]
+ This stops the synth and frees the associated memory - on the server. Your Synth Object still exists in the interpreter, but you can't use it any more. A Synth Object represents a synth on the server; since you got rid of the synth on the server, the Synth Object represents something that doesn't exist. If you attempt to send the "free" message again, you'll get an error. For this reason, it's a good idea to get rid of the Synth Object at the same time:
+ [pre]
+ variableHoldingSynth.free;
+ variableHoldingSynth = nil;
+ [/pre]
+ If you accidentally send "free" to an already-freed Synth, the interpreter will cause an error, and program execution will stop. If you accidentally send "free" to a variable set to "nil", nothing will happen. Proactively avoiding mistakes like this is good programming practice.
+ </para>
+ </section>
+ </section> <!-- Ends "SynthDef and Synth" Section --> <!-- SC-Basic_Programming-SynthDef_and_Synth- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses">
+ <title>Busses</title>
+ <para>
+ SuperCollider busses work just like busses in other audio creation contexts, which work similarly to busses used to transport humans. Busses are used to send audio from one place to another, and in SuperCollider they can also be used to send control-rate signals. Each SuperCollider bus is given an index number, which are integers starting at 0. Audio-rate busses and control-rate busses are independent, and are given an independent set of index numbers. Any number of unique signals can be routed into a bus, and any number of receivers can take signals from a bus - but the signal will be the sum of all the input signals. In other words, if you want to send two different sets of signals, you need two different busses with different index numbers.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses-Audio_Rate_Bus_Numbers">
+ <title>Audio-Rate Bus Numbers</title>
+ <para>
+ There are special audio-rate busses reserved automatically by the server. These interact with the audio interface, allowing you to get sound from its inputs, and send sound to its outputs. The lowest audio-rate bus numbers are reserved for audio interface outputs, each channel receiving an independent bus. The bus numbers just above those are reserved for audio interface inputs, each channel receiving an independent bus.
+ </para>
+ <para>
+ For a simple audio interface with two channels each for input and output, the pre-reserved audio-rate bus numbers would be these:
+ <itemizedlist>
+ <listitem><para>0 for left channel output</para></listitem>
+ <listitem><para>1 for right channel output</para></listitem>
+ <listitem><para>2 for left channel input</para></listitem>
+ <listitem><para>3 for right channel input</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Now you can change the first argument of the "Out" UGen as desired!
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses-Out_and_In_UGens">
+ <title>Out and In UGens</title>
+ <para>
+ The "Out" UGen is discussed in the !!SynthDef section!!. What it does is take a signal and route it to the specified bus number. The "In" UGen performs a similar action: take a signal from a bus number, and make it available for use.
+ </para>
+ <para>
+ This is the syntax to use for "Out":
+ [pre]
+ Out.ar( busNumber, audioRateUGen );
+ [/pre]
+ or
+ [pre]
+ Out.kr( busNumber, controlRateUGen );
+ [/pre]
+ The UGen enclosed here should not be enclosed in a Function. If the UGen provides multi-channel output, "Out" will automatically route the lowest channel to the specified bus number, the next channel to the next highest bus number, and so on. This way, you can achieve stereo output with one "Out" UGen.
+ </para>
+ <para>
+ This is the syntax to use for "In":
+ [pre]
+ In.ar( busNumber, numberOfChannels );
+ [/pre]
+ or
+ [pre]
+ In.kr( busNumber, numberOfChannels );
+ [/pre]
+ Whereas "Out" automatically outputs the right number of channels based on how many you provide, "In" requires that you specify how many channels you want it to fetch for you.
+ </para>
+ <para>
+ When created with this form, both of these UGens automatically connect to the default server, stored in the single-letter "s" variable by the interpreter.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses-Bus_Objects">
+ <title>Bus Objects</title>
+ <para>
+ As SynthDef and Synth represent things stored on the server, the interpreter provides us with an instantiable "Bus" Class that represents the server's busses. In many programs that you write, you won't need to use a Bus Object - particularly when you're doing simple input and output with the automatically-reserved bus numbers. But, like the SynthDef and Synth Classes make it easier to deal with synthdefs and synths on the server (which are very difficult to deal with directly), the Bus Class makes it easier to deal with busses on the server, and provides some extra functionality to boot!
+ </para>
+ <para>
+ The primary advantage of using Bus Objects is that you don't have to keep track of bus numbers, whether they're being used, and how mnany channels are being routed. For simple input and output of audio-rate signals, you're better off simply remembering the bus numbers
+ </para>
+ <para>
+ The "new" message creates a new Bus. Here is the syntax:
+ [pre]
+ var myBusVariable = Bus.audio( serverName, numberOfChannels );
+ [/pre]
+ or
+ [pre]
+ var myBusVariable = Bus.control( serverName, numberOfChannels );
+ [/pre]
+ The interpreter takes "numberOfChannels" busses on the "serverName" server, and groups them together for multi-channel use in one Bus Object, which it returns to you. The "numberOfChannels" argument is optional; if you leave it out, the Bus Object will have only one bus, for single-channel signals.
+ </para>
+ <para>
+ The interpreter also keeps track of which bus numbers are used for which Bus Objects, so the signals will never get confused. Of course, you can still route signals through those bus numbers without using the Bus Object, but the Bus Class helps us to keep things straight.
+ </para>
+ <para>
+ The following messages can also be used with Bus Objects:
+ {|
+ ! Message !! Example !! Purpose
+ |-
+ | index || b.index; || Returns the lowest bus number used by this Bus
+ |-
+ | numChannels || b.numChannels; || Returns the number of busses used by this Bus
+ |-
+ | rate || b.rate; || Returns "audio" or "control," depending on whether the Bus is audio-rate or control-rate.
+ |-
+ | server || b.server; || Returns the name of the server that the Bus represents. The default server is "localhost".
+ |}
+ </para>
+ <para>
+ When you are done with a Bus, you can release the channels for use by other Bus Objects:
+ [pre]
+ myBusVariable.free;
+ myBusVariable = nil;
+ [/pre]
+ Like when sending the "free" message to a Synth Object, you should set the variable name of a "free'd" Bus to "nil". This will prevent you from accidentally sending audio there after the Bus is released.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses-Control_Rate_Bus_Example">
+ <title>Using Busses: Control-Rate Example</title>
+ <para>
+ The best way to understand how and when to use a bus is to see them in action.
+ [pre]
+ ( // execute first: prepare the server
+ var busAudioSynth =
+ {
+ arg bus, freqOffset = 0;
+
+ Out.ar( 0, SinOsc.ar( freq:( In.kr(bus) + freqOffset ), mul:0.1 ) );
+ };
+
+ var busControlSynth =
+ {
+ arg bus, freq = 400;
+
+ Out.kr( bus, SinOsc.kr( freq:1, mul:( freq/40 ), add:freq ) );
+ };
+
+ SynthDef( \tutorialAudioBus, busAudioSynth ).send( s );
+ SynthDef( \tutorialControlBus, busControlSynth ).send( s );
+
+ b = Bus.control( s );
+ )
+
+ ( // execute second: create synths
+ x = Synth.new( \tutorialControlBus, [\bus, b] ); // control synth
+ y = Synth.after( x, \tutorialAudioBus, [\bus, b] ); // low audio synth
+ z = Synth.after( x, \tutorialAudioBus, [\bus, b, \freqOffset, 200] ); // high audio synth
+ )
+
+ ( // commands to free each Object
+ x.free; x = nil; // control synth
+ y.free; y = nil; // low audio synth
+ z.free; z = nil; // high audio synth
+ b.free; b = nil; // control bus
+ )
+ [/pre]
+ This example contains three stages: prepare the server, create the synths, destroy the synths. These three stages will become familiar as you program in SuperCollider, whether or not you use busses frequently. The example is fairly complicated, so the code is explained here:
+ <itemizedlist>
+ <listitem><para>"busAudioSynth" Function: Accepts two arguments, and creates an audio-rate <code>SinOsc</code>, routed to the left output channel. The frequency is determined by a control-rate bus given as an argument, and optionally with an offset that can be supplied as an argument.</para></listitem>
+ <listitem><para>"busControlSynth" Function: Accepts two arguments, and creates a control-rate <code>SinOsc</code>, routed to the bus given as an argument. Can also be given a frequency; the value produced by the synth is intended to be used to control pitch. The centre pitch of the oscillation is "freq", and the range of oscillation is one-twentieth the size of "freq" (one-fourtieth both higher and lower than "freq").</para></listitem>
+ <listitem><para>SynthDef: These commands are straight-forward. They send the synthesis definitions to the server.</para></listitem>
+ <listitem><para><code>b = Bus.control( s );</code> : This should also be straight-forward. A single-channel control bus is created, and assigned to the pre-declared variable "b".</para></listitem>
+ <listitem><para>For synth creation, x is assigned a control-rate synth, while y and z are assigned audio-rate synths. Each synth is given the variable "b", which refers to our control-rate bus. "z" is also given an argument for \freqOffset, which makes its frequency 200 Hz higher than the synth assigned to "y".</para></listitem>
+ <listitem><para>Don't worry about the "after" message for now. It's explained in !! the section about Ordering !!</para></listitem>
+ </itemizedlist>
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses-Control_Rate_Example-Global_Variables">
+ <title>Why Use Global Variables</title>
+ <para>
+ Since this is just an example, and not an actual program, the program uses four automatically-declared global variables: b, x, y, and z. Because these variables are shared with everything, it's especially important to set them to "nil" when you're done. If this were going to be written into a real program, it would be a good idea to change the variables to something which can't be accessed by other programs.
+ </para>
+ </section>
+ <section id="sect-Musicians_GuideSC-Basic_Programming-Busses-Control_Rate_Example-Why_Use_a_Bus">
+ <title>Why Use a Bus</title>
+ <para>
+ The control-rate bus in this example might seem trivial and pointless to you, especially since the use of a UGen to control frequency has already been illustrated in other examples. For this particular program, a control-rate UGen would probably have been a better choice, but remember that this is just an example.
+ </para>
+ <para>
+ Here are some main advantages to using a control-rate Bus over a UGen:
+ # The signal can be changed without sending the "set" message to the audio-rate UGen, simply by changing the input to the bus.
+ # Input to the bus can be produced by any number of control-rate UGen's.
+ # The signal in the bus can be received by more than one UGen, as it is in this example. One thousand audio-rate UGen's powered by 25 control-rate UGen's is a much better solution than if each audio-rate UGen were powered by its own control-rate UGen.
+ # Busses can be accessed quickly and efficiently from any place in the program that has access to the variable holding the Bus. It's easier and safer (less error-prone) than making all of your UGen's equally accessible.
+ </para>
+ <para>
+ Some of these advantages could be seen as disadvantages. Whether you should use a Bus or a UGen depends on the particular application. The simpler solution is usually the better one, as long as you remember to avoid repetition!
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses-Control_Rate_Example-Special_Note">
+ <title>Special Note about Control-Rate Busses</title>
+ <para>
+ Control-rate Bus'ses are a great way to enhance the flexibility of your program. The best part is that, in order to use a control-rate Bus, the UGen doesn't even need to have been written to accomodate it.
+ [pre]
+ { SinOsc.ar( freq:In.kr( controlRateBus, 1 ), mul:0.2 ); }.play;
+ [/pre]
+ Now you've managed to spice up an otherwise-boring synth!
+ </para>
+ <para>
+ Also, control-rate Bus'ses don't need to be constantly changing. Unlike an audio-rate Bus, a control-rate Bus will hold the last-inputted value until another value is provided. You can the value of a control-rate Bus with the "set" message (and a single argument, which is the value). You can also get the current value, whether created by "set" or a UGen, by using the "get" message, and sending a Function with one argument.
+ [pre]
+ (
+ var bus = Bus.control( s );
+ bus.set( 12 );
+ bus.get( { arg val; val.postln; } );
+ bus.free; bus = nil;
+ )
+ [/pre]
+ When running this example, you'll notice that the "12" doesn't get posted until ''after'' the program finishes with "nil". This is because of the '''latency''' between when the interpreter asks the server to do something, and when the server does it. The amount of time it takes for the server to complete a command is usually very small, but as you can see, it can make an important difference to your program. This latency is also the reason that you can't call "SynthDef.new( ... )" and "Synth.new( ... )" at the exact same time.
+ </para>
+ <para>
+ This latency is also the reason that we have to provide a single-argument Function as an argument to the "get" Function. Since the Function won't immediately be able to get the value of the bus from the server, we can't expect the value to be returned by the Function. Instead, when "get" gets the value of the bus from the server, it runs the Function that you gave it.
+ </para>
+ </section>
+ </section> <!-- Ends "Using Busses: Control-Rate Example" Section -->
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Busses-Audio_Rate_Bus_Example">
+ <title>Using Busses: Audio-Rate Example</title>
+ <para>
+ [pre]
+ (
+ var tutorialDecayPink =
+ {
+ arg outBus = 0, effectBus,
+ direct = 0.5; // controls proportion of "direct" / "processed" sound
+ var source;
+
+ // Decaying pulses of PinkNoise.
+ source = Decay2.ar( in:Impulse.ar( freq:1, phase:0.25 ),
+ attackTime:0.01,
+ decayTime:0.2,
+ mul:PinkNoise.ar
+ );
+
+ Out.ar( outBus, (source*direct) ); // main output
+ Out.ar( effectBus, (source*(1-direct)) ); // effects output
+ };
+
+ var tutorialDecaySine =
+ {
+ arg outBus = 0, effectBus,
+ direct = 0.5; // controls proportion of "direct" / "processed" sound
+ var source;
+
+ // Decaying pulses of a modulating Sine wave.
+ source = Decay2.ar( in:Impulse.ar( freq:0.3, phase: 0.25),
+ attackTime:0.3,
+ decayTime:1,
+ mul:SinOsc.ar( freq:SinOsc.kr( freq:0.2, mul:110, add:440) )
+ );
+
+ Out.ar(outBus, (source*direct) ); // main output
+ Out.ar(effectBus, (source*(1-direct)) ); // effects output
+ };
+
+ var tutorialReverb =
+ {
+ arg outBus = 0, inBus; // default outBus is audio interface
+ var input;
+
+ input = In.ar( inBus, 1 );
+
+ 16.do( { input = AllpassC.ar( in:input,
+ maxdelaytime:0.04,
+ delaytime:{ Rand(0.001,0.04) }.dup,
+ decaytime:3
+ )
+ }
+ );
+
+ Out.ar( outBus, input );
+ };
+
+ // send synthesis information to the server
+ SynthDef( \tutorialReverb, tutorialReverb ).send( s );
+ SynthDef( \tutorialDecayPink, tutorialDecayPink ).send( s );
+ SynthDef( \tutorialDecaySine, tutorialDecaySine ).send( s );
+
+ // reserve an effects Bus
+ b = Bus.audio( s );
+ )
+
+ (
+ x = Synth.new( \tutorialReverb, [\inBus, b] );
+ y = Synth.before( x, \tutorialDecayPink, [\effectBus, b] );
+ z = Synth.before( x, \tutorialDecaySine, [\effectBus, b, \outBus, 1] );
+ )
+
+ // Change the balance of "wet" to "dry"
+ y.set( \direct, 1 ); // only direct PinkNoise
+ z.set( \direct, 1 ); // only direct Sine wave
+ y.set( \direct, 0 ); // only reverberated PinkNoise
+ z.set( \direct, 0 ); // only reverberated Sine wave
+ y.set( \direct, 0.5 ); // original PinkNoise
+ z.set( \direct, 0.5 ); // original Sine wave
+
+ ( // commands to free each Object
+ x.free; x = nil;
+ y.free; y = nil;
+ z.free; z = nil;
+ b.free; b = nil;
+ )
+ [/pre]
+ </para>
+ <para>
+ I'm not going to explain this example as extensively as the previous one. It's definitely the most complex example so far. It's better if you figure out what the parts do by playing with them yourself. The bus works by routing audio from the <code>\tutorialDecayPink</code> and <code>\tutorialDecaySine</code> synths into the <code>\tutorialReverb</code> synth. The first two synths can be controlled to put all, none, or some of their signal into the bus (so that it goes through the <code>\tutorialReverb</code> synth), or straight out the audio interface (bypassing the <code>\tutorialReverb</code> synth). Notice that the ''same'' effects processor is operating on two different input sources.
+ </para>
+ </section> <!-- Ends "Using Busses: Audio-Rate Example" Section -->
+ </section> <!-- Ends "Busses" Section --> <!-- SC-Basic_Programming-Busses- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Ordering_and_Other_Features">
+ <title>Ordering and Other Synth Features</title>
+ <para>
+ This section discusses the important topic of creating and enforcing an "order" on the server. Because this is done with Functions (or methods) from the Synth Class, other useful Functions from the Class are discussed here.
+ </para>
+ <section id="sect-Musicians_Guide-C-Basic_Programming-Ordering_and_Other_Features-Ordering">
+ <title>Ordering</title>
+ <para>
+ Ordering is instructing the server to calculate in a particular order. The audio synthesized by the server takes the same form as any other digital audio: a series of !!samples!! are played at a particular speed (called !!sample rate!!), each with a set number of bits per sample (called !!bit rate!! or sample format). For each sample, the server calculates the signal at that point in a pre-determined order. Each sample is calculated from scratch, so if a particular UGen depends on the output of another UGen, the other one had better be calculated first.
+ </para>
+ <para>
+ Consider the following example:
+ [pre]
+ { SinOsc.ar( freq:SinOsc.kr( freq:1, add:500, mul:10 ), mul:0.2 ); }.play;
+ [/pre]
+ What happens if the server calculates the audio-rate UGen first? It wouldn't have a frequency. This is another one of those things which the interpreter takes care of automatically when we run Function rather than create a Synth. Since it's often preferable to use a synth instead of a Function, we need some way to control the order of execution. The interpreter and the server are only so good at guessing what we need, after all.
+ </para>
+ <para>
+ There are two methods in the Synth Class that we can use to inform the server about our desired order of execution: "before" and "after". They represent a small extension to the "new" method, and they work like this:
+ [pre]
+ Synth.before( variableHoldingSynth, nameOfSynthDef, ListOfArguments );
+ [/pre]
+ and
+ [pre]
+ Synth.after( variableHoldingSynth, nameOfSynthDef, ListOfArguments );
+ [/pre]
+ And it works just as it looks, too: the server creates a new synth, adds it before or after the synth represented by "variableHoldingSynth" (depending on which Function you use), and uses "nameOfSynthDef" and "ListOfArguments" just as in the "add" method.
+
+ This example, from the !!"Bus"!! section, uses the "after" Function to ensure that the control-rate synth is calculated before the audio-rate synths that depend on it.
+ [pre]
+ ( // execute first: prepare the server
+ var busAudioSynth =
+ {
+ arg bus, freqOffset = 0;
+
+ Out.ar( 0, SinOsc.ar( freq:( In.kr(bus) + freqOffset ), mul:0.1 ) );
+ };
+
+ var busControlSynth =
+ {
+ arg bus, freq = 400;
+
+ Out.kr( bus, SinOsc.kr( freq:1, mul:( freq/40 ), add:freq ) );
+ };
+
+ SynthDef( \tutorialAudioBus, busAudioSynth ).send( s );
+ SynthDef( \tutorialControlBus, busControlSynth ).send( s );
+
+ b = Bus.control( s );
+ )
+
+ ( // execute second: create synths
+ x = Synth.new( \tutorialControlBus, [\bus, b] ); // control synth
+ y = Synth.after( x, \tutorialAudioBus, [\bus, b] ); // low audio synth
+ z = Synth.after( x, \tutorialAudioBus, [\bus, b, \freqOffset, 200] ); // high audio synth
+ )
+
+ ( // commands to free each Object
+ x.free; x = nil; // control synth
+ y.free; y = nil; // low audio synth
+ z.free; z = nil; // high audio synth
+ b.free; b = nil; // control bus
+ )
+ [/pre]
+ In this case, the control-rate synth is created before the audio-rate synths - probably the easier way to think about it. Even so, it's possible to add them in the opposite order with a little extra thought.
+ </para>
+ <para>
+ The other example from the !!"Bus"!! section used the "before" Function to ensure that the "pink noise" and "sine wave" UGen's were calculated before the "reverberation" UGen. Especially since these are all audio-rate UGen's, the server would not reasonably know which to calculate first, so you need to let it know.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-C-Basic_Programming-Ordering_and_Other_Features-Changing_the_Order">
+ <title>Changing the Order</title>
+ <para>
+ SuperCollider offers equally easy-to-use methods to change the order of execution.
+ </para>
+ <para>
+ To move a synth's execution after another:
+ [pre]
+ variableHoldingSynth.moveAfter( variableHoldingAnotherSynth );
+ [/pre]
+ </para>
+ <para>
+ To move a synth's execution before another:
+ [pre]
+ variableHoldingSynth.moverBefore( variableHoldingAnotherSynth );
+ [/pre]
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-C-Basic_Programming-Ordering_and_Other_Features-Replace_a_Running_Synth">
+ <title>Replace a Running Synth</title>
+ <para>
+ The server allows you to replace a running synth with a newly-created one, maintaining all of the ordering relationships.
+ </para>
+ <para>
+ This is the syntax:
+ [pre]
+ variableHoldingNewSynth = Synth.replace( variableHoldingSynthToReplace, nameOfSynthDef, ListOfArguments );
+ [/pre]
+ The "variableHoldingNewSynth" will often be the same as the "variableHoldingSynthToReplace," but not always. When you use this Function, the synth being replaced is freed from the server (equivalent to running "free"), so that variable should always be assigned something.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-C-Basic_Programming-Ordering_and_Other_Features-Pausing_and_Restarting_a_Synth">
+ <title>Pausing and Restarting a Synth</title>
+ <para>
+ The server allows you to temporarily pause and later re-start a synth, without freeing and re-creating it.
+ </para>
+ <para>
+ To pause a synth:
+ [pre]
+ variableHoldingSynth.run( false );
+ [/pre]
+ </para>
+ <para>
+ To re-start a synth:
+ [pre]
+ variableHoldingSynth.run( true );
+ [/pre]
+ </para>
+ </section>
+ </section> <!-- Ends "Ordering and Other Synth Features" Section --> <!-- SC-Basic_Programming-Ordering_and_Other_Features- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Scheduling">
+ <title>Scheduling</title>
+ <para>
+ The practice of scheduling allows you to making things happen in a pre-determined amount of time. Scheduling is very different from ordering: ordering is a primarily technical consideration to ensure that the server synthesizes the sound in the right order; scheduling is a primarily musical consideration that allows you to control the perceived time that things happen.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Scheduling-Clocks">
+ <title>Clocks</title>
+ <para>
+ SuperCollider's clocks have two main functions: they know what time it is, and they know what time things are supposed to happen.
+ </para>
+ <para>
+ There are three types of clocks, which each do slightly different things:
+ <itemizedlist>
+ <listitem><para>TempoClock: These clocks are aware of metre (time signature) changes, and have an adjustable tempo. They are to be used for scheduling musical events, and they run with a high priority.</para></listitem>
+ <listitem><para>SystemClock: This clock always runs in seconds. It can be used to schedule musical events, since it runs with a high priority. There is only one SystemClock.</para></listitem>
+ <listitem><para>AppClock: These clocks always run in seconds. They are to be used for graphic events and other non-musical things not discussed in this guide. These clocks do not run with a high priority, so they can be temporarily "side-lined" by a TempoClock or the SystemClock, if one of those has something to do urgently.</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Scheduling-Default_Clocks">
+ <title>Default Clocks</title>
+ <para>
+ The SuperCollider interpreter provides two default clocks, and one default pseudo-clock.
+ </para>
+ <para>
+ The <code>SystemClock</code> always operates in seconds, and it can be used to schedule musical events, but usually this isn't necessary.
+ </para>
+ <para>
+ The <code>TempoClock.default</code> runs at 60 beats-per-minute by default (equal to one beat per second). Since it's accessible from anywhere within a program, any tempo changes will have an effect on the scheduling of the entire program - so be careful! If you don't want something to be effected by tempo changes, you can create a new TempoClock just for that part of the program. If you will be using this clock frequently, you can assign it to a variable like this:
+ [pre]
+ var t = TempoClock.default;
+ [/pre]
+ </para>
+ <para>
+ The <code>thisThread.clock</code> is not really a clock in itself, but refers to the clock which is responsible for scheduling the part of the program where the command is written. It can be a little bit tricky working with this clock, since it may be either the SystemClock or a TempoClock.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Scheduling-Finding_the_Current_Time">
+ <title>Finding the Current Time</title>
+ <para>
+ Using the "beats" method on a clock will return that clock's current time. Try running each of the following:
+ [pre]
+ SystemClock.beats;
+ TempoClock.default.beats;
+ thisThread.clock.beats;
+ [/pre]
+ </para>
+ <para>
+ This can be useful for scheduling events in an absolute way, or for a number of other things.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Scheduling-Relative_Scheduling">
+ <title>Relative Scheduling</title>
+ <para>
+ The standard way to schedule things is in a certain number of beats from now. If you're scheduling on a SystemClock, one beat is equal to one second. If you're scheduling on a TempoClock, one beat is equal to whatever the current setting is.
+ </para>
+ <para>
+ To schedule things on a clock, use the "sched" Function:
+ [pre]
+ nameOfClock.sched( beatsFromNow, FunctionToExecute );
+ [/pre]
+ The interpreter will let you schedule just about anything, but there's no point in scheduling something other than a Function: scheduling a five won't have any effect - try it!
+ [pre]
+ SystemClock.sched( 5, 5 );
+ [/pre]
+ It looks like nothing happens. The 5 does happen, but... well... it doesn't do anything. Scheduling a Function ''will'' do something:
+ [pre]
+ SystemClock.sched( 5, { 5.postln; } );
+ [/pre]
+ When you run this, there are two things to notice:
+ <itemizedlist>
+ <listitem><para>The interpreter prints out "SystemClock" first. This is to let you know that it did the scheduling as requested.</para></listitem>
+ <listitem><para>The five prints out endlessly, in five-second intervals. For an explanation, see "Repeated Scheduling"</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Scheduling-Repeated_Scheduling">
+ <title>Repeated Scheduling</title>
+ <para>
+ If you schedule a Function that returns a number, the interpreter will schedule the Function to re-run in that many beats.
+ </para>
+ <para>
+ This will print "5" every five seconds, until you press [Esc] to stop execution.
+ [pre]
+ SystemClock.sched( 5, { 5.postln; } );
+ [/pre]
+ </para>
+ <para>
+ To avoid this, you can end your Function with "nil", which has been done sometimes through this guide.
+ [pre]
+ SystemClock.sched( 5, { 5.postln; nil; } );
+ [/pre]
+ This will print "5" in five seconds, and then stop.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Scheduling-TempoClock_Class">
+ <title>Working with the TempoClock Class</title>
+ <para>
+ Here is a brief explanation of some Functions available with the TempoClock Class. Throughout this section, the variable "t" is used to represent any particular TempoClock.
+ </para>
+ <para>
+ [pre]
+ var t = TempoClock.new( tempo, beats );
+ [/pre]
+ This creates a new TempoClock. The arguments are optional, and have the following meanings:
+ * tempo: tempo of the clock, given in beats per second. To input a value in beats-per-minute, divide it by 60. Defaults to 60 beats per minute, or one per second.
+ * beats: starts the clock at this time. Default is zero.
+ </para>
+ <para>
+ [pre]
+ t.stop;
+ t = nil;
+ [/pre]
+ Equivalent to the "free" method for a Synth of Bus Object. This stops the clock, discards all scheduled events, and releases the resources used to run the clock. Setting the variable to "nil" afterwards is optional, but recommended, to avoid later programming mistakes.
+ </para>
+ <para>
+ [pre]
+ t.clear;
+ [/pre]
+ Discards all scheduled events, but keeps the clock running.
+ </para>
+ <para>
+ [pre]
+ t.tempo;
+ [/pre]
+ Returns the current tempo in beats-per-second.
+ </para>
+ <para>
+ [pre]
+ t.tempo_( newTempo );
+ [/pre]
+ Allows you to change the clock's tempo. The new tempo should be in beats-per-second. To input a tempo in beats-per-minute, divide the value by 60.
+ </para>
+ <para>
+ [pre]
+ t.play( Function );
+ [/pre]
+ Schedules the Function to begin execution on the next beat.
+ </para>
+ <para>
+ There are many other Functions in the TempoClock Class, related to absolute scheduling, scheduling with bars, and conversion of beats to and from seconds.
+ </para>
+ </section>
+ </section> <!-- Ends "Scheduling" Section --> <!-- SC-Basic_Programming-Scheduling- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Getting_Help">
+ <title>How to Get Help</title>
+ <para>
+ Knowing how to get help in SuperCollider is going to play a large part in determining whether you have a productive or frustrating relationship with the language and its components. There are a large number of ways to get help, but here are some of the most helpful.
+ </para>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Getting_Help-Official_Help_Files">
+ <title>Use the SuperCollider Help Files</title>
+ <para>
+ SuperCollider comes with an extensive collection of help files, which contain the answers to most of your problems. The difficulty will be in finding the solution - it's not always located where you think it is, because it often isn't the solution you think it will be.
+ </para>
+ <para>
+ On Fedora Linux systems, the main help file is located at [file:///usr/share/SuperCollider/Help/Help.html this URL], and it can be viewed in any web browser. It may also be helpful to browse the directory structure of the help files, located at [file:///usr/share/SuperCollider/Help this URL], which can also be viewed in your web browser.
+ </para>
+ <para>
+ If you're looking for further explanations of material in this tutorial, you could start by reviewing the [file:///usr/share/SuperCollider/Help/Tutorials/Getting-Started/Getting%20Started%20With%20SC.html Getting Started With SuperCollider] tutorial, on which this document is based. The sections in that tutorial roughly correspond to the sections in this guide.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Getting_Help-IRC">
+ <title>Internet Relay Chat (IRC)</title>
+ <para>
+ If you know how to use Internet Relay Chat (IRC), you can join the #supercollider channel on the Freenode network. The channel does not usually have a large number of participants or a lot of activity, but the users are some of the most polite and helpful on the internet.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Getting_Help-Email">
+ <title>Email</title>
+ <para>
+ If you feel comfortable sending an email to a mailing list, you can use the [http://www.beast.bham.ac.uk/research/sc_mailing_lists.shtml sc-users] list. If you decide to subscribe to this list, be aware that it receives a large amount of mail every day.
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Getting_Help-SuperCollider_Website">
+ <title>The SuperCollider Website</title>
+ <para>
+ The SuperCollider web site at SourceForge offers links to many resources. It is available [http://supercollider.sourceforge.net/ here].
+ </para>
+ </section>
+ </section> <!-- Ends "How to Get Help" Section --> <!-- SC-Basic_Programming-Getting_Help- -->
+
+ <section id="sect-Musicians_Guide-SC-Basic_Programming-Legal_Attribution">
+ <title>Legal Attribution</title>
+ <para>
+ This portion of the Fedora Musicians' Guide, called "Basic Programming with SuperCollider," is a derivative work of the, "Getting Started With SuperCollider" tutorial. The original work was created by Scott Wilson, James Harkins, and the SuperCollider development team. It is available on the internet at [http://supercollider.svn.sourceforge.net/viewvc/supercollider/trunk/common/… this location].
+ </para>
+ <para>
+ The original document, like all SuperCollider documentation, is licenced under the Creative Commons' [http://creativecommons.org/licenses/by-sa/3.0/ Attribution Share-Alike 3.0 Unported] licence.
+ </para>
+ <para>
+ This usage should in no way be construed as an endorsement of the Fedora Project, the Musicians' Guide, or any other party by the SuperCollider development team.
+ </para>
+ </section> <!-- Ends "Legal Attribution" Section --> <!-- SC-Basic_Programming-Legal_Attribution- -->
+</section> <!-- End "Basic Programming with SuperCollider -->
\ No newline at end of file
diff --git a/en-US/SuperCollider/SuperCollider-Composing.xml b/en-US/SuperCollider/SuperCollider-Composing.xml
new file mode 100644
index 0000000..60e6efb
--- /dev/null
+++ b/en-US/SuperCollider/SuperCollider-Composing.xml
@@ -0,0 +1,576 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<section id="sect-Musicians_Guide-SuperCollider-Composing">
+ <title>Composing with SuperCollider</title>
+ <para>
+ This section is an explanation of the creative thought-process that went into creating the SuperCollider composition that we've called "Method One," for which the source and exported audio files are available below in the !!"Included Files"!! section.
+ </para>
+ <para>
+ It is our hope that, in illustrating how we developed this composition from a single SinOsc command, you will learn about SuperCollider and its abilities, about how to be creative with SuperCollider, and how a simple idea can turn into something of greater and greater complexity.
+ </para>
+ <para>
+ As musicians, our goal is to learn enough SuperCollider to make music; we don't want to have to memorize which parameters do what for which functions, and in which order to call them. We want to know what they do for us musically. Explicitly calling parameters, and making comments about what does what, so that we can return later and change musical things, are going to help our musical productivity, at the expense of slowing down our typing.
+ </para>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Tutorial_Files">
+ <title>Tutorial Files</title>
+ <para>
+ The following files represent complete versions of the program. You should try to complete the program yourself before reviewing these versions:
+ <itemizedlist>
+ <listitem><para>[[User:Crantila/FSC/Synthesizers/SuperCollider/FSC_method_1.sc|Method One]]</para></listitem>
+ <listitem><para>[[User:Crantila/FSC/Synthesizers/SuperCollider/FSC_method_1-short.sc|Method One (Short)]]</para></listitem>
+ <listitem><para>[[Media:FMG-Method_One.flac|FLAC Recording of "Method One"]]</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ FSC_method_1.sc : This is an extensively-commented version of the source code. The comments not only describe the way the code works, but pose some problems and questions that you may wish to work on, to increase your knowledge of SuperCollider. The problem with the verbosity of the comments is that it can be difficult to read the code itself, as it would be written in a real program.
+ </para>
+ <para>
+ FSC_method_1-short.sc : This is a less-commented version of the source code. I've also re-written part of the code, to make it more flexible for use in other programs. The differences between this, and code that I would have written for myself only, are trivial.
+ </para>
+ <para>
+ FSC_method_1.flac : This is a recording that I produced of the program, which I produced in Ardour.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Inspiration">
+ <title>Inspiration</title>
+ <para>
+ The intention of this program is to represent one way to write a SuperCollider program. I decided to take one class, SinOsc, and use it for "everything." Here, "everything" means any function that returns a sound, or any function that directly controls a SinOsc.
+ </para>
+ <para>
+ In order to fill up time, I decided to employ a three-part "rounded binary" form: ABA' or "something, something new, then the first thing again." This is kind of like a sine oscillation, too!
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Designing_the_First_Part">
+ <title>Designing the First Part</title>
+ <procedure>
+ <step><para>I started with something simple: a single SinOsc: <code>{ SinOsc.ar(); }.play;</code></para></step>
+ <step><para>This is not exciting: it just stays the same forever, and it only uses one channel! So, I added another SinOsc to the right channel, using the [ , ] array notation. The result is <code>{ [ SinOsc.ar(), SinOsc.ar() ] }.play;</code></para></step>
+ <step><para>Now it sounds balanced, at least, like it's coming from the middle. But it's still boring, so I added a frequency-changing SinOsc to the right channel, resulting in <code>{ [ SinOsc.ar(), SinOsc.ar(SinOsc.kr(1,50,300)) ] }.play;</code></para></step>
+ <step><para>Since that's difficult to read, and since I know that I'm just going to keep adding things, I expand the code a little bit to make it more legible. This gives me [pre]{
+ var left = SinOsc.ar();
+ var right = SinOsc.ar( SinOsc.kr( 1, 50, 300 ) );
+
+ [ left, right ]
+
+ }.play;[/pre]I define a variable holding everything I want in the left channel, then the same for the right. I still use the [ , ] array notation to create a stereo array. Remember that SuperCollider functions return the last value stated, so it might look like the stereo array is ignored, but because this array is what is returned by the function contained between { and }, it is this array that gets played by the following ".play;"</para></step>
+ <step><para>I also added a frequency controller to the left SinOsc, and realized that it's getting a bit difficult to read again, especially if I wanted to add another parameter to the SinOsc.ar objects. So I placed the SinOsc.kr's into their own variables: frequencyL and frequencyR. This results in [pre]{
+ var frequencyL = SinOsc.kr( freq:10, mul:200, add:400 );
+ var frequencyR = SinOsc.kr( freq:1, mul:50, add:150 );
+
+ var left = SinOsc.ar( frequencyL );
+ var right = SinOsc.ar( frequencyR );
+
+ [ left, right ]
+
+ }.play;[/pre]</para></step>
+ <step><para>Now I can experiment with the frequency-changing SinOsc's, to make sure that I get things just right. When I realize what the parameters do, I make a note for myself (see "FSC-method-1-.sc"), so that it will be easy to adjust it later. I also explicitly call the parameters. This isn't necessary, but it also helps to avoid future confusion. Most programmers would not explicitly call the parameters, but we're musicians, not programmers.</para></step>
+ <step><para>The left channel has something like a "melody," so I decided to add a drone-like SinOsc to it. This is easy, of course, because any SinOsc left alone is automatically a drone! But, where should it be added? Into the "left" variable, of course. We'll create an array using [ , ] array notation. There are two things that I would do at this point to help with future readability:</para>
+ <substeps>
+ <step><para>Align all of the left-channel SinOsc's vertically (using tabs and spaces), so that each line is one sound-generating UGen.</para></step>
+ <step><para>At the end of each line, write a small comment describing what the UGen on that line doesn.</para></step>
+ </substeps>
+ </step>
+ <step><para>Now the volume is a problem. For most sound-producing UGen's, the "mul" argument controls the volume. For most of those, the default is "1.0," and anything greater will create distorted output. The physics and computer science factors that wind up creating distortion are rather complicated, and it isn't necessary to understand them. What we need to know is that, if the output of a UGen (or some UGen's) sounds distorted, then we should probably adjust the "mul" argument. Sometimes, of course, you may prefer that distorted output.
+ <itemizedlist>
+ <listitem><para>It seems that, when you're using multiple SinOsc's in one output channel, the "mul" of all of them must not add to more than 1.0</para></listitem>
+ <listitem><para>We're using two output channels (left and right). We'll leave the right channel alone for now, because it has only one output UGen.</para></listitem>
+ <listitem><para>So, I'll change add a "mul" argument to each of the left-channel UGen's, to 0.5</para></listitem>
+ </itemizedlist>
+ </para></step>
+ <step><para>Now we can't hear the left channel, because the right channel is too loud! Playing with volumes (sometimes called "adjusting levels" for computers) is a constant aesthetic concern for all musicians. Add a "mul" argument to the right channel, and set it to what seems an appropriate volume for the moment. It will probably change later, but that's okay.</para></step>
+ <step><para>But let's add another dimension to this: there's no reason to keep the volume static, because we can use a SinOsc to change it periodically! I added a SinOsc variable called "volumeL," which I used as the argument to "mul" for the "frequencyL" SinOsc in the left channel.</para></step>
+ <step><para>And now the sheer boredom of the drone in the left channel becomes obvious. I decide to make it more interesting by adding a series of overtones (an overtone is...). I decide to add six, then experiment with which frequencies to add. But, every time I adjust one frequency, I have to re-calculate and change all the others. So I decide to add a variable for the drone's frequency: "frequencyL_drone". This way, after finding the right intervals, I can easily adjust all of them just by changing the variable. I've decided on drone*1, 2, 5, 13, and 28. These are more or less arbitrary, and I arrived on them through experimentation. Of course, the drone will be ''way'' too loud.</para></step>
+ <step><para>Having <code> SinOsc.ar( [frequencyL_drone,2*frequencyL_drone,5*frequencyL_drone,13*frequencyL_drone,28*frequencyL_drone], mul:0.1 )</code> in your program is not easy to read, and actually it doesn't work out volume-balance-wise (for me, at least): the high frequencies are too loud, and the lower ones are not loud enough. In retrospect, I should have created a variable for the "mul" of these drones, so I could adjust them easily in proportion. But, I didn't.</para></step>
+ <step><para>A constant drone isn't as much fun as one that slowly changes over time. So, I changed the "frequencyL_drone" value to a SinOsc.kr UGen. Because it's supposed to be a "drone," it should change only very gradually, so I used a very small freqeuncy argument. It still moves quite quickly, but people won't want to listen to this too long, anyway!</para></step>
+ <step><para>I did something similar with the right channel, addding a slowly-changing drone and overtones above it.</para></step>
+ <step><para>After some final volume adjustments, I feel that I have completed the first part. There is no way to know for sure that you've finished until it happens. Even then, you may want to change your program later.</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Designing_the_Second_Part">
+ <title>Designing the Second Part</title>
+ <para>
+ The next thing that I did was to design the second part. This will not join them together yet, and I'm going to focus on something completely different, so I decided to do this in a separate file.
+ </para>
+ <para>
+ My inspiration for this part came from experimenting with the drones of the first part. There are a virtually unlimited number of combinations of sets of overtones that could be created, and the combinations of discrete frequencies into complex sounds is something that has fascinated me for a long time. Moreover, when thousands of discrete frequencies combine in such a way as to create what we think of as "a violin playing one note," it seems like a magical moment.
+ </para>
+ <para>
+ I'm going to build up a set of pseudo-random tones, adding them one at a time, in set increments. As you will see, this introduces a number of problems, primarily because of the scheduling involved with the one-by-one introduction of tones, and keeping track of those tones.
+ </para>
+ <para>
+ The fact that there are ten tones also poses a problem, because it might require a lot of typing. We'll see solutions to that, which use SuperCollider's programming features to greatly increase the efficiency.
+ </para>
+ <para>
+ Although we've already solved the musical problems (that is, we know what we want this part to sound like), the computer science (programming) problems will have to be solved the old-fashioned way: start with something simple, and build it into a complex solution.
+ </para>
+ <para>
+ First I will develop the version used in FSC-method-1.sc, then the version used in FSC-method-1-short.sc
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Creating_Ten_Pseudo-Random-Tones">
+ <title>Creating Ten Pseudo-Random Tones</title>
+ <procedure>
+ <step><para>We'll start again with something simple, that we know how to do.
+ [pre]{
+ SinOsc.ar();
+ }.play;[/pre]</para></step>
+ <step><para>We already know that we want this to produce stereo output, and we already know that we're going to be using enough SinOsc's that we'll need to reduce "mul." Keeping in mind that there will be ten pitches, and two SinOsc's for each of them, set both of those things now, keeping just one pitch for now.</para></step>
+ <step><para>The first challenge is to implement pseudo-randomness. We'll use the number.rand function to generate a pseudo-random number (integer, actually), but if run as <code>50.rand</code>, we will get a result between 0 and 50. As a frequency, this is not useful: most audio equipment cannot produce pitches below 20 Hz, and many people have problems hearing very low frequencies. This means that we'll need to add a value to .rand's output (like <code>100 + 50.rand</code>, which will yield an integer between 100 and 150). I decided to go with a value between 200 Hz and 800 Hz instead, largely because I felt like it. Try setting the freq with the .rand call.</para></step>
+ <step><para>I hope you didn't end up with two different frequencies! If you did, you'll need to use a variable to temporarily store the pseduo-random frequency, so that both sides can use it.</para></step>
+ <step><para>Now we need to make ten of these, so copy-and-paste until there are ten different stereo pitches at once.[pre]{
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ]
+ }.play;[/pre]</para></step>
+ <step><para>It doesn't work: you'll also have to rename your frequency-setting variable each time.[pre]{
+ var frequency1 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency1, mul:0.01 ), SinOsc.ar( freq:frequency1, mul:0.01 ) ]
+ var frequency2 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency2, mul:0.01 ), SinOsc.ar( freq:frequency2, mul:0.01 ) ]
+ var frequency3 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency3, mul:0.01 ), SinOsc.ar( freq:frequency3, mul:0.01 ) ]
+ var frequency4 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency4, mul:0.01 ), SinOsc.ar( freq:frequency4, mul:0.01 ) ]
+ var frequency5 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency5, mul:0.01 ), SinOsc.ar( freq:frequency5, mul:0.01 ) ]
+ var frequency6 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency6, mul:0.01 ), SinOsc.ar( freq:frequency6, mul:0.01 ) ]
+ var frequency7 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency7, mul:0.01 ), SinOsc.ar( freq:frequency7, mul:0.01 ) ]
+ var frequency8 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency8, mul:0.01 ), SinOsc.ar( freq:frequency8, mul:0.01 ) ]
+ var frequency9 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency9, mul:0.01 ), SinOsc.ar( freq:frequency9, mul:0.01 ) ]
+ var frequency0 = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency0, mul:0.01 ), SinOsc.ar( freq:frequency0, mul:0.01 ) ]
+ }.play;[/pre]</para></step>
+ <step><para>It still doesn't work! The error given in the "SuperCollider output" window is not easy to understand, but it means "You have to put all of your variable declarations before everything else."[pre]{
+ var frequency1 = 200 + 600.rand;
+ var frequency2 = 200 + 600.rand;
+ var frequency3 = 200 + 600.rand;
+ var frequency4 = 200 + 600.rand;
+ var frequency5 = 200 + 600.rand;
+ var frequency6 = 200 + 600.rand;
+ var frequency7 = 200 + 600.rand;
+ var frequency8 = 200 + 600.rand;
+ var frequency9 = 200 + 600.rand;
+ var frequency0 = 200 + 600.rand;
+
+ [ SinOsc.ar( freq:frequency1, mul:0.01 ), SinOsc.ar( freq:frequency1, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency2, mul:0.01 ), SinOsc.ar( freq:frequency2, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency3, mul:0.01 ), SinOsc.ar( freq:frequency3, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency4, mul:0.01 ), SinOsc.ar( freq:frequency4, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency5, mul:0.01 ), SinOsc.ar( freq:frequency5, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency6, mul:0.01 ), SinOsc.ar( freq:frequency6, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency7, mul:0.01 ), SinOsc.ar( freq:frequency7, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency8, mul:0.01 ), SinOsc.ar( freq:frequency8, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency9, mul:0.01 ), SinOsc.ar( freq:frequency9, mul:0.01 ) ]
+ [ SinOsc.ar( freq:frequency0, mul:0.01 ), SinOsc.ar( freq:frequency0, mul:0.01 ) ]
+ }.play;[/pre]</para></step>
+ <step><para>It still doesn't work! SuperCollider is confused because I was been lazy and didn't include enough semicolons. The error we get is, "Index not an Integer," which is a clue as to what SuperCollider is trying to do (but it's irrelevant). The real problem is that SuperCollider interprets our ten stereo arrays as all being part of the same statement. We don't want them to be the same statement, however, because we want ten ''different'' stereo arrays to be played. Fix this problem by putting a semicolon at the end of each stereo array. You don't ''need'' to include one at the end of the last statement, because SuperCollider assumes the end of the statement when it encounters a } (end-of-function marker) after it. Since we're still building our code, we might move these around or add something aftwards, so it's better to include a semicolon at the end of each stereo array.</para></step>
+ <step><para>Now the file plays successfully, but with a disappointing result. If you can't already see the problem, try to think of it before continuing to read.</para></step>
+ <step><para>Only one SinOsc array gets played, and it's the last one. This is because the last statement is returned by the function that ends at } and it is that result which gets sent to the following .play</para></step>
+ <step><para>To fix this, and ensure that all of the stereo arrays are played, you should remove the .play from the end of the function, and add a .play to each stereo array statement. You end up with [pre]{
+ var frequency1 = 200 + 600.rand;
+ var frequency2 = 200 + 600.rand;
+ var frequency3 = 200 + 600.rand;
+ var frequency4 = 200 + 600.rand;
+ var frequency5 = 200 + 600.rand;
+ var frequency6 = 200 + 600.rand;
+ var frequency7 = 200 + 600.rand;
+ var frequency8 = 200 + 600.rand;
+ var frequency9 = 200 + 600.rand;
+ var frequency0 = 200 + 600.rand;
+
+ [ SinOsc.ar( freq:frequency1, mul:0.01 ), SinOsc.ar( freq:frequency1, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency2, mul:0.01 ), SinOsc.ar( freq:frequency2, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency3, mul:0.01 ), SinOsc.ar( freq:frequency3, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency4, mul:0.01 ), SinOsc.ar( freq:frequency4, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency5, mul:0.01 ), SinOsc.ar( freq:frequency5, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency6, mul:0.01 ), SinOsc.ar( freq:frequency6, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency7, mul:0.01 ), SinOsc.ar( freq:frequency7, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency8, mul:0.01 ), SinOsc.ar( freq:frequency8, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency9, mul:0.01 ), SinOsc.ar( freq:frequency9, mul:0.01 ) ].play;
+ [ SinOsc.ar( freq:frequency0, mul:0.01 ), SinOsc.ar( freq:frequency0, mul:0.01 ) ].play;
+ }[/pre]</para></step>
+ <step><para>When you execute this, no sound is produced, but SuperCollider outputs "a Function." Can you think of why this happens? It's because you wrote a function, but never told SuperCollider to evaluate it! At the end of execution, SuperCollider just throws away the function, because it's never used. This is the same thing that happened to the first nine stereo arrays - they were created, but you never said to do anything with them, so they were just thrown out. We need to execute the function. Because it doesn't produce a UGen, we can't use "play," so we have to use "value" instead. You can choose to do either of these:[pre]{ ... }.value;[/pre] or [pre]var myFunction = { ... }; myFunction.value;[/pre]</para></step>
+ <step><para>This gives us yet another error, as if we can't play the stereo arrays! In fact, we can't - and we didn't do it in the first part, either. We play'ed the result of returning a stereo array from a function. The subtle difference isn't important yet - we're just trying to make this work! Use { and } to build a function for .play to .play</para></step>
+ <step><para>Now make the correction nine more times.</para></step>
+ <step><para>When you play execute the resulting code, you probably get something that sounds quite "space-age." Execute it a few times, to see the kind of results you get.</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Scheduling_the_Tones">
+ <title>Scheduling the Tones</title>
+ <procedure>
+ <step><para>The next step is to get these started consecutively, with 5-second pauses after each addition. For this we will use a TempoClock, and since this is the only thing that we're doing, we'll just use the default one called TempoClock.default. I don't feel like typing that, however, so we're going to define an alias variable: <code>var t_c = TempoClock.default;</code> You could put that in the main function, but I suggest putting it before the main function. This way, if we want to write another function later, then it can also access t_c.</para></step>
+ <step><para>The default TempoClock has a default tempo of one beat per second (1 Hz). This will be good enough for us. If you wanted to change the tempo, remember that you can enter a metronome setting (which is "beats per minute") by dividing the metronome setting by 60. So a metronome's 120 beats per minute would be given to a new TempoClock as <code>TempoClock.new( 120/60 )</code>. Even though you could do that ahead of time and just write "2," inputting it as "120/60" makes it clearer what tempo you intend to set.</para></step>
+ <step><para>You can schedule something on a TempoClock by using <code>t_c.sched( x, f );</code>, where "f" is a function to execute, and "x" is when it should be done, measured as the number of beats from now. So we can schedule our SinOsc like this: [pre]t_c.sched( 1, {{[ SinOsc.ar( freq:frequency1, mul:0.01 ), SinOsc.ar( freq:frequency1, mul:0.01 ) ]}.play;} );[/pre]</para></step>
+ <step><para>Schedule the rest, in intervals of five beats (which is five seconds). They will all be scheduled virtually instantaneously (that is, the computer will notice the slight delay between when each one is scheduled, but humans will not). I started at one beat from now, to insert a slight pause before the sound begins.</para></step>
+ <step><para>If you've done this correctly, then we should get a build-up of ten pitches. But they never stop! This is going to take some more ingenuity to solve, because we can't just make a stereo array, play it, then throw it away. We need to hold onto the stereo array, so that we can stop it. The first step here is to store the stereo arrays in variables, and subsequently schedule them. You will end up with something like this:[pre]var sinosc1 = { [ SinOsc.ar( freq:frequency1, mul:0.01 ), SinOsc.ar( freq:frequency1, mul:0.01 ) ] };
+ // the other nine...
+
+ t_c.sched( 1, { sinosc1.play; } );
+ // the other nine...[/pre]</para></step>
+ <step><para>It should still work, but we after all that cutting-and-pasting, we still haven't managed to turn off the SinOsc's. We need to "free" the object that was returned when we used the "play" function. We need to declare yet more variables: <code>var so1, so2, so3, so4, so5, so6, so7, so8, so9, so0;</code> should appear anywhere before the scheduler.</para></step>
+ <step><para>Now adjust all the scheduling commands so they look like this: <code>t_c.sched( 1, { so1 = sinosc1.play; } );</code></para></step>
+ <step><para>Now you can add ten of these, after the existing scheduling commands: <code>t_c.sched( 51, { so1.free; } );</code>. Be sure to schedule each one for 51 beats, so that they all turn off simultaneously, 5 beats after the last pitch is added.</para></step>
+ <step><para>It should work successfully. If it doesn't, then compare what you have to this, which does work:[pre]var t_c = TempoClock.default;
+
+ {
+ var frequency1 = 200 + 600.rand;
+ var frequency2 = 200 + 600.rand;
+ var frequency3 = 200 + 600.rand;
+ var frequency4 = 200 + 600.rand;
+ var frequency5 = 200 + 600.rand;
+ var frequency6 = 200 + 600.rand;
+ var frequency7 = 200 + 600.rand;
+ var frequency8 = 200 + 600.rand;
+ var frequency9 = 200 + 600.rand;
+ var frequency0 = 200 + 600.rand;
+
+ var sinosc1 = { [ SinOsc.ar( freq:frequency1, mul:0.01 ), SinOsc.ar( freq:frequency1, mul:0.01 ) ] };
+ var sinosc2 = { [ SinOsc.ar( freq:frequency2, mul:0.01 ), SinOsc.ar( freq:frequency2, mul:0.01 ) ] };
+ var sinosc3 = { [ SinOsc.ar( freq:frequency3, mul:0.01 ), SinOsc.ar( freq:frequency3, mul:0.01 ) ] };
+ var sinosc4 = { [ SinOsc.ar( freq:frequency4, mul:0.01 ), SinOsc.ar( freq:frequency4, mul:0.01 ) ] };
+ var sinosc5 = { [ SinOsc.ar( freq:frequency5, mul:0.01 ), SinOsc.ar( freq:frequency5, mul:0.01 ) ] };
+ var sinosc6 = { [ SinOsc.ar( freq:frequency6, mul:0.01 ), SinOsc.ar( freq:frequency6, mul:0.01 ) ] };
+ var sinosc7 = { [ SinOsc.ar( freq:frequency7, mul:0.01 ), SinOsc.ar( freq:frequency7, mul:0.01 ) ] };
+ var sinosc8 = { [ SinOsc.ar( freq:frequency8, mul:0.01 ), SinOsc.ar( freq:frequency8, mul:0.01 ) ] };
+ var sinosc9 = { [ SinOsc.ar( freq:frequency9, mul:0.01 ), SinOsc.ar( freq:frequency9, mul:0.01 ) ] };
+ var sinosc0 = { [ SinOsc.ar( freq:frequency0, mul:0.01 ), SinOsc.ar( freq:frequency0, mul:0.01 ) ] };
+
+ var so1, so2, so3, so4, so5, so6, so7, so8, so9, so0;
+
+ t_c.sched( 1, { so1 = sinosc1.play; } );
+ t_c.sched( 6, { so2 = sinosc2.play; } );
+ t_c.sched( 11, { so3 = sinosc3.play; } );
+ t_c.sched( 16, { so4 = sinosc4.play; } );
+ t_c.sched( 21, { so5 = sinosc5.play; } );
+ t_c.sched( 26, { so6 = sinosc6.play; } );
+ t_c.sched( 31, { so7 = sinosc7.play; } );
+ t_c.sched( 36, { so8 = sinosc8.play; } );
+ t_c.sched( 41, { so9 = sinosc9.play; } );
+ t_c.sched( 46, { so0 = sinosc0.play; } );
+
+ t_c.sched( 51, { so1.free; } );
+ t_c.sched( 51, { so2.free; } );
+ t_c.sched( 51, { so3.free; } );
+ t_c.sched( 51, { so4.free; } );
+ t_c.sched( 51, { so5.free; } );
+ t_c.sched( 51, { so6.free; } );
+ t_c.sched( 51, { so7.free; } );
+ t_c.sched( 51, { so8.free; } );
+ t_c.sched( 51, { so9.free; } );
+ t_c.sched( 51, { so0.free; } );
+
+ }.value;[/pre]</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Optimizing_the_Code">
+ <title>Optimizing the Code</title>
+ <para>
+ Hopefully, while working through the previous sections, you got an idea of how tedious, boring, difficult-to-read, and error-prone this sort of copy-and-paste programming can be. It's ridiculous, and it's poor programming:
+ <itemizedlist>
+ <listitem><para>We're using a lot of variables and variable names. They're all just used once or twice, too.</para></listitem>
+ <listitem><para>When you copy-and-paste code, but change it a little, you might make a mistake in that little change.</para></listitem>
+ <listitem><para>When you copy-and-paste code, when you make a mistake, you have to copy-and-paste to fix it everywhere.</para></listitem>
+ <listitem><para>Repetition is the enemy of high-quality code. It is much better to write something once and re-use that same code.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Thankfully, SuperCollider provides three things that will greatly help to solve these problems - at least for our current situation:
+ <itemizedlist>
+ <listitem><para>Arrays can be used to hold multiple instances of the same thing, all referred to with essentially the same name. We're already doing something similar, (sinosc1, sinosc2, etc.) but arrays are more flexible.</para></listitem>
+ <listitem><para>Functions can be written once, and executed as many times as desired.</para></listitem>
+ <listitem><para>Loops also provide a means to write code once, and execute it many times. As you will see, they are useful in situations different from functions.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ It should be noted that, while it is good practise to program like this, it is also optional. You will probably find, though, that writing your programs well in the first place ends up saving huge headaches in the future.
+ </para>
+ <procedure>
+ <step><para>The first thing we'll do is write a function to deal with generating the stereo arrays of SinOsc's.</para></step>
+ <step><para>Take the code required to generate one stereo array of SinOsc's with a pseudo-random frequency. Put it in a function, and declare a variable for it (I used the name "func").</para></step>
+ <step><para>Now remove the frequency1 (etc.) variables, and change the sinosc1 (etc.) variables to use the new function. Make sure that the code still works in the same way. It's much easier to troubleshoot problems when you make only one change at a time!</para></step>
+ <step><para>At this point, we've eliminated ten lines of code, and made ten more lines easier to read by eliminating the subtle copy-and-paste changes. If you can't manage to work it out, refer to the FSC_method_1.sc file for tips.</para></step>
+ <step><para>We can eliminate ten more lines of code by using a loop with an array. Let's change only one thing at a time, to make it easier to find a problem, if it should arise. Start by commenting out the lines which declare and initialize sinosc1, sinosc2, and so on.</para></step>
+ <step><para>Then declare a ten-element array in the same place: <code>var sinosc = Array.new( 10 );</code></para></step>
+ <step><para>The next part is to write code to get ten func.value's into the array. To add something to an array in SuperCollider, we use the "add" method: <code>sinosc.add( thing_to_add );</code> There is a small wrinkle to this, described in the SuperCollider documentation. It's not important to understand (for musical reasons, that is - it is explained on this help page), but when you add an element to an array, you ''should'' re-assign the array to the variable-name: <code>sinosc = sinosc.add( thing_to_add )</code> Basically it works out like this: if you don't re-assign, then there is a chance that the array name only includes the elements that were in the array before the "add" command was run.</para></step>
+ <step><para>With this, we are able to eliminate a further level of redundancy in the code. Ten exact copies of <code>sinosc = sinosc.add( { func.value; } );</code> Now, ten lines that look almost identical actually are identical. Furthermore, we don't have to worry about assigning unique names, or even about index numbers, as in other programming languages. SuperCollider does this for us!</para></step>
+ <step><para>This still won't work, because we need to adjust the rest of the function to work with this array. The scheduling commands be changed to look something like this: <code>t_c.sched( 1, { so1 = sinosc[0].play; } );</code> Since arrays are indexed from 0 to 9, those are the index numbers of the first ten objects in the array.</para></step>
+ <step><para>Remember that you need to put all of your variable declarations ''before'' anything else.</para></step>
+ <step><para>It ''should'' still work. Let's use a loop to get rid of the ten identical lines.</para></step>
+ <step><para>In SuperCollider, <code>x.do( f );</code> will send the "value" message to the function "f" "x" times. So, to do this ten times, we should write <code>10.do( { sinosc = sinosc.add( { func.value; } ); } );</code> and get rid of the other ones. This is very powerful for simple things that must be done multiple times, because you are definitely not going to make a copy-and-paste error, because it's easy to see what is being executed, and because it's easy to see how many times it is being executed.</para></step>
+ <step><para>Now let's reduce the repetitiveness of the scheduling. First, replace so1, so2, etc. with a ten-element array. Test it to ensure that the code still works.</para></step>
+ <step><para>Getting the next two loops working is a little bit more complicated. We know how to run the exact same code in a loop, but we don't know how to change it subtly (by supplying different index numbers for the array, for example). Thankfully, SuperCollider provides a way to keep track of how many times the function in a loop has already been run. The first argument given to a function in a loop is the number of times that the function has ''already'' been executed. The first time it is run, the function receives a 0; if we're using a <code>10.do( ... );</code> loop, then the last time the function is run, it receives a 9 because the function has already been executed 9 times. Since our ten-element array is indexed from 0 to 9, this works perfectly for us.</para></step>
+ <step><para>The code to free is shorter: <code>10.do( { arg index; t_c.sched( 51, { so[index].free; } ); } );</code> This can look confusing, especially written in one line, like it is. If it helps, you might want to write it like this instead:
+ [pre]
+ 10.do
+ ({ arg index;
+ t_c.sched( 51, { so[index].free; } );
+ });
+ [/pre]Now it looks more like a typical function.</para></step>
+ <step><para>The next step is to simplify the original scheduling calls in a similar way, but it's slightly more complicated because we have to schedule a different number of measures for each call. With a little math, this is also not a problem - it's just a simple linear equation:[pre]number_of_measures = 5 * array_index + 1[/pre]Try to write this loop by yourself, before going to the next step.</para></step>
+ <step><para>If you missed it, my solution is
+ [pre]
+ 10.do( { arg index; t_c.sched( ((5*index)+1), { so = so.add( sinosc[index].play; ); } ); } );
+ [/pre] which includes some extra parentheses to ensure that the math is computed in the right order.</para></step>
+ <step><para>The code is already much shorter, easier to understand, and easier to expand or change. There is one further optimzation that we can easily make: get rid of the sinosc array. This simply involves replacing <code>sinosc[index]</code> with what all of its elements are: <code>{func.value;}</code></para></step>
+ <step><para>The resulting program is a little different from what ended up in FSC_method_1.sc, but produces the same output. What I have is this:
+ [pre]
+ var t_c = TempoClock.default;
+
+ {
+ var so = Array.new( 10 );
+
+ var func =
+ {
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ];
+ };
+
+ 10.do( { arg index; t_c.sched( ((5*index)+1), { so = so.add( {func.value;}.play; ); } ); } );
+ 10.do( { arg index; t_c.sched( 51, { so[index].free; } ); } );
+
+ }.value;
+ [/pre]</para></step>
+ <step><para>Finally, assign this Function to a variable (called "secondPart", perhaps), and remove the "value" Function-call. If we leave that in, the Function will execute before the rest of the program begins!</para></step>
+ </procedure>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Making_a_Useful_Function_Out_of_the_Second_Part">
+ <title>Making a Useful Section out of the Second Part</title>
+ <para>
+ This section describes the reasons for the differences between the second part's Function that was just created, and the Function that appears in "FSC_method_1-short.sc". It all comes down to this: the current solution is tailor-made for this particular program, and would require significant adaptation to be used anywhere else; I want to re-design the Function so that it can be used anywhere to begin with, while still defaulting to the behaviour desired for this program.
+ </para>
+ <para>
+ You can skip this section, and return later. The actions for the rest of the tutorial remain unchanged whether you do or do not make the modifications in this section.
+ </para>
+ <para>
+ Here's what I have from the previous step:
+ [pre]
+ var t_c = TempoClock.default;
+
+ var secondPart =
+ {
+ var so = Array.new( 10 );
+
+ var func =
+ {
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ];
+ };
+
+ 10.do( { arg index; t_c.sched( ((5*index)+1), { so = so.add( {func.value;}.play; ); } ); } );
+ 10.do( { arg index; t_c.sched( 51, { so[index].free; } ); } );
+
+ };
+ [/pre]
+ This Function is the perfect solution if you want ten pseudo-random pitches between 200 Hz and 800 Hz, and a five-second pause between each one. If you want nine or eleven pitches, if you want them to eb between 60 Hz and 80Hz, if you want a six-second pause between each - you would have to modify the Function. If you don't remember how it works, or if you give it to a friend, you're going to have to figure out how it works before you modify it. This is not an ideal solution.
+ </para>
+ <para>
+ Let's solve these problems one at a time, starting with allowing a different number of SinOsc synths to be created. We know that we'll have to create an argument, and that it will have to be used wherever we need the number of SinOsc's. Also, to preserve functionality, we'll make a default assignment of 10. Try to accomplish this yourself, making sure to test your Function so that you know it works. Here's what I did:
+ [pre]
+ var t_c = TempoClock.default;
+
+ var secondPart =
+ {
+ arg number_of_SinOscs = 10;
+
+ var so = Array.new( number_of_SinOscs );
+
+ var func =
+ {
+ var frequency = 200 + 600.rand;
+ [ SinOsc.ar( freq:frequency, mul:0.01 ), SinOsc.ar( freq:frequency, mul:0.01 ) ];
+ };
+
+ number_of_SinOscs.do( { arg index; t_c.sched( ((5*index)+1), { so = so.add( {func.value;}.play; ); } ); } );
+ number_of_SinOscs.do( { arg index; t_c.sched( 51, { so[index].free; } ); } );
+
+ };
+ [/pre]
+ The "do" loop doesn't need a constant number; it's fine with a variable. What happens when you pass a bad argument, like a string? This would be an easy way to sabotage your program, and in almost any other programming context it would concern us, but this is just audio programming. If somebody is going to try to create "cheese" SinOsc's, it's their own fault for mis-using the Function.
+ </para>
+ <para>
+ Now let's modify the Function so that we can adjust the range of frequencies that the Function will generate. We know that we'll need two more arguments, and that they'll have to be used in the equation to calculate the frequency. But we'll also need to do a bit of arithmetic, because of the way the "rand" Function works (actually we don't - see the "rand" Function's help file). Also, to preserve functionality, we'll make default assignments of 200 and 800. Try to accomplish this yourself, making sure that you test the Function so you know it works. Here's what I did:
+ [pre]
+ var t_c = TempoClock.default;
+
+ var secondPart =
+ {
+ arg number_of_SinOscs = 10,
+ pitch_low = 200,
+ pitch_high = 800;
+
+ var so = Array.new( number_of_SinOscs );
+
+ var func =
+ {
+ var freq = pitch_low + (pitch_high - pitch_low).rand;
+ [ SinOsc.ar( freq:freq, mul:0.01),
+ SinOsc.ar( freq:freq, mul:0.01) ];
+ };
+
+ number_of_SinOscs.do( { arg index; t_c.sched( ((5*index)+1), { so = so.add( {func.value;}.play; ); } ); } );
+ number_of_SinOscs.do( { arg index; t_c.sched( 51, { so[index].free; } ); } );
+
+ };
+ [/pre]
+ Notice that I changed the name of the variables, and the indentation in the "func" sub-Function, to make it easier to read. This isn't a particularly difficult change.
+ </para>
+ <para>
+ Now let's allow the user to set the length of time between each SinOsc appears. We will need one more argument, used in the scheduling command. Try to accomplish this yourself, and if you run into difficulty, the next paragraph contains some tips.
+ </para>
+ <para>
+ The change to the "do" loop which schedules the SinOsc's to play is almost trivial. My new argument is called "pause_length", (meaning "the length of the pause, in seconds, between adding each SinOsc"), so I get this modification:
+ [pre]
+ number_of_SinOscs.do(
+ {
+ arg time;
+ secondPart_clock.sched( (1+(time*5)), { sounds = sounds.add( func.play ); } );
+ });
+ [/pre]
+ Again, I changed the indentation, and the names of the variables in this sub-Function. Recall that the "1+" portion is designed to add a one-second pause to the start of the Function's execution. The problem comes in the next "do" loop, where we have to know how the number of beats from now will be five seconds after the last SinOsc is added. We'll have to calculate it, so I added a variable to store the value after it's calculated. This also allows us to return it, as a convenience to the Function that called this one, so that it knows how long until this Function is finished. Try adding this yourself, then testing the Function to ensure that it works. I got this:
+ [pre]
+ var t_c = TempoClock.default;
+
+ var secondPart =
+ {
+ arg number_of_SinOscs = 10,
+ pitch_low = 200,
+ pitch_high = 800,
+ pause_length = 5;
+
+ var so = Array.new( number_of_SinOscs );
+
+ var when_to_stop = ( 1 + ( pause_length * number_of_SinOscs ) );
+
+ var func =
+ {
+ var freq = pitch_low + (pitch_high - pitch_low).rand;
+ [ SinOsc.ar( freq:freq, mul:0.01),
+ SinOsc.ar( freq:freq, mul:0.01) ];
+ };
+
+ number_of_SinOscs.do(
+ {
+ arg time;
+ t_c.sched( (1+(time*5)), { so = so.add( func.play ); } );
+ });
+
+ t_c.sched( when_to_stop,
+ {
+ number_of_SinOscs.do( { arg index; so[index].free; } );
+ nil;
+ });
+
+ when_to_stop;
+ };
+ [/pre]
+ I decided to "invert" the "free-ing" of the SinOsc's. Rather than scheduling number_of_SinOscs Function-calls at some point in the future, I decided to schedule one thing: a "do" loop that does the work. The indentation looks strange, but sometimes there's not much you can do about that. The "when_to_stop" variable must be the last thing in the Function, so that the interpreter returns it to the Function's caller.
+ </para>
+ <para>
+ In order to retain the "bare minimum" robustness to be used elsewhere, we can't rely on the "TempoClock.default" clock having the tempo we expect, and we certainly can't rely on it being declared as "t_c". The solution is quite easy: create a new TempoClock within the Function.
+ [pre]
+ var t_c = TempoClock.new; // default tempo is one beat per second
+ [/pre]
+ We could hypothetically use the "SystemClock", since we're measuring time strictly in seconds. But, using a TempoClock is preferred for two reasons:
+ <orderedlist>
+ <listitem><para>It has the word "tempo" in its name, and it's designed for scheduling musical events; the "SystemClock" is for system events.</para></listitem>
+ <listitem><para>We can easily extend this in the future to use a "TempoClock" set to a different tempo.</para></listitem>
+ </orderedlist>
+ </para>
+ <para>
+ There are some further ways to improve this Function, making it more robust (meaning that it will work consistently in a greater range of circumstances). Here are things that could be done to improve the Function, with an explanation of why it would make the Function more robust:
+ <itemizedlist>
+ <listitem><para>Made the clock an argument, allowing this Function to schedule events on a clock belonging to some other Function. Since all clocks respond to the "sched" message, we could even accept the "SystemClock" or "AppClock". The default value would still be <code>TempoClock.new</code></para></listitem>
+ <listitem><para>Use absolute scheduling rather than relative scheduling. Depending on how long the server and interpreter take to process the commands, it could lead to significant delays if the Function is asked to create a lot of SinOsc's.</para></listitem>
+ <listitem><para>Create one SynthDef (with an argument) for all of the synths. Especially when asked to create a large numbe of SinOsc's, this will lead to faster processing and lower memory consumption. On the other hand, it increases the complexity of the code a little bit, requiring more testing.</para></listitem>
+ <listitem><para>Each SinOsc is currently created with the same "mul" argument, regardless of how many SinOsc's are created. Set as it is, when asked to create 51 SinOsc's, the signal would become distorted. If you're puzzled about why 51, remember that for each SinOsc the Function is asked to create, it currently creates two: one for the left and one for the right audio channel.</para></listitem>
+ <listitem><para>Allow the SynthDef to be passed in as an argument, with the requirement that such a SynthDef would need to accept the "freq" and "mul" arguments. This is going out on a limb a bit, and requires careful explanation in comments to ensure that the Function is used correctly. You will also need to test what happens if the Function is used incorrectly. Crashing the server application is a bad thing to do, especially without a warning.</para></listitem>
+ <listitem><para>Use a Bus to cut the number of synths in half, so that one synth will be sent both to the left and right channels. Alternatively, you could add special stereo effects.</para></listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ As you can see, there are a lot of ways to improve this Function even further; there are almost certainly more ways than listed here. Before you distribute your Function, you would want to be sure to test it thoroughly, and add helpful comments so that the Function's users know how to make the Function do what they want. These are both large topics in themselves, so I won't give them any more attention here.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Composing-Joining_the_Two_Parts">
+ <title>Joining the Two Parts</title>
+ <para>
+ Now it is time to join the two parts, and ensure a clean transition between them. My reasons for building the first part as a SynthDef, but the second part as a function are explained in the FSC_part_1.sc file. Additional reasons include my desire to illustrate the use of both possibilities, and because the second part stops itself (so it can be a function which is executed and forgotten), whereas the first part does not stop itself (so we'll need to hold onto the synth, to stop it ourselves).
+ </para>
+ <procedure>
+ <step><para>I copy-and-pasted both parts into a new file, leaving the other original code in tact, in case I want to build on them in the future. Be sure to copy over the <code>var t_c = TempoClock.default;</code> definition from the second part.</para></step>
+ <step><para>By default, the two parts would both start playing at the same time (give it a try!) This isn't what we want, however, so you'll need to erase the "play" command from both parts' functions. We'll also need some way to refer to them, so declare the second part as a variable (I've used the name, "secondPart,"), but don't worry about the first part yet. Don't forget the semicolon at the end of the function declaration!</para></step>
+ <step><para>To join the two parts, I'm going to use function that does all the scheduling. This is similar to a "main" function, which are used in most programming languages. Although they are optional in SuperCollider, it just makes sense to use one function that does all the scheduling, and nothing else: that way, when you have problems with the scheduling, or you want to make an adjustment or addition to the program, you can easily find the place where the scheduling happens. If your scheduling commands were spread out through the source file, it would be much more difficult to find and modify the scheduling commands.</para></step>
+ <step><para>Our first job is to determine which variables we'll need to use: just one, which will be assigned the currently-running \FirstPart Synth. Also, if you didn't previously assign "TempoClock.default" to the variable "t_c", then it makes sense to do this now.</para></step>
+ <step><para>The next thing our function must do is guarantee that we're going to have the right tempo. Use the "tempo_" Function with an argument in beats-per-second, to assign "TempoClock.default" a tempo of one beat per second.</para></step>
+ <step><para>The next and last thing will be to schedule our sounds. First, we need to determine which events will need to be scheduled, and then at what times.</para>
+ <substeps>
+ <step><para>Since \FirstPart is a SynthDef, we'll need to start it and stop it ourselves. Since it happens two times in the intended program, we'll need to do it twice.</para></step>
+ <step><para>secondPart is a Function, and it stops itself when it's finished. We'll need to start it once and let it go.</para></step>
+ <step><para>Just in case something takes a while to process, we'll start the first \FirstPart on beat one, rather than beat zero. We'll let it play for 60 seconds the first time, and 30 seconds the second time.</para></step>
+ <step><para>In order to schedule the second appearance of \FirstPart, we need to know how long secondPart will take. Let's inspect the function and calculate how many beats it will take.
+ <itemizedlist>
+ <listitem><para>1 beat of silence at the beginning,</para></listitem>
+ <listitem><para>5 beats between the entrance of each SinOsc,</para></listitem>
+ <listitem><para>10 SinOsc's,</para></listitem>
+ <listitem><para>5 beats after the last SinOsc until the function stops.</para></listitem>
+ <listitem><para>This gives us <code>1 + ( 5 * 9 ) + 5 = 51</code>. Why <code>5 * 9</code>? Because although there are ten SinOsc's, there are only nine spaces between them; the last five-second space happens ''after'' the last SinOsc.</para></listitem>
+ </itemizedlist>
+ </para></step>
+ <step><para>This gives us the following schedule:
+ <itemizedlist>
+ <listitem><para>1 beat: start \FirstPart</para></listitem>
+ <listitem><para>61 beats: stop \FirstPart</para></listitem>
+ <listitem><para>61 beats: start secondPart</para></listitem>
+ <listitem><para>113 beats: start \FirstPart</para></listitem>
+ <listitem><para>143 beats: stop \FirstPart</para></listitem>
+ </itemizedlist>
+ </para></step>
+ </substeps>
+ </step>
+ <step><para>Try to schedule the events for yourself, then test your program to make sure that it works as you intended. Here's what I wrote:
+ [pre]
+ t_c.sched( 1, { sound = Synth.new( \FirstPart ); } );
+ t_c.sched( 61, { sound.free; } );
+ t_c.sched( 61, { secondPart.value; nil; } );
+ t_c.sched( 113, { sound = Synth.new( \FirstPart ); } );
+ t_c.sched( 143, { sound.free; } );
+ [/pre]
+ Why is the "nil" required after "secondPart"? Because that function returns a number. As you know, any scheduled function which returns a number will re-schedule itself to run that many beats after the previous execution began. Since "secondPart" returns the number of seconds it takes to finish, it will always be re-started as soon as it finishes. Including "nil" disallows this repetition.
+ </para></step>
+ </procedure>
+ </section>
+</section>
\ No newline at end of file
diff --git a/en-US/SuperCollider/SuperCollider-Exporting.xml b/en-US/SuperCollider/SuperCollider-Exporting.xml
new file mode 100644
index 0000000..e058926
--- /dev/null
+++ b/en-US/SuperCollider/SuperCollider-Exporting.xml
@@ -0,0 +1,46 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<section id="sect-Musicians_Guide-SuperCollider-Exporting">
+ <title>Exporting Sound Files</title>
+ <para>
+ This section explains one way to record your SuperCollider programs, so that you can share them with friends who don't have SuperCollider on their computer.
+ </para>
+
+ <section id="sect-Musicians_Guide-SC-Non_Real_Time_Synthesis">
+ <title>Non-Real-Time Synthesis</title>
+ <para>
+ SuperCollider allows you to synthesze audio output to an audio file. Doing this requires using OSC commands on the server, the "DiskOut" UGen, the "Buffer" UGen, and other relatively advanced concepts. The built-in help file located [file:///usr/share/SuperCollider/Help/UGens/Playback%20and%20Recording/DiskOut.html here] contains some help with the DiskOut UGen, and links to other useful help files. This method is not further discussed here.
+ </para>
+ </section>
+
+ <section id="sect-Musicians_Guide-SC-Recording_SuperColliders_Output">
+ <title>Recording SuperCollider's Output (Tutorial)</title>
+ <para>
+ Since SuperCollider outputs its audio signals to the JACK sound server, any other JACK-aware program has the opportunity to record, process, and use them. This portion of the tutorial will help you to record SuperCollider's output in Ardour. Due to the advanced nature of SuperCollider, the text assumes that you have a basic knowledge of how to work with Ardour. If not, you may find it helpful to refer to the [[User:Crantila/FSC/Recording/Ardour|Ardour chapter]] of the Musicians' Guide.
+ </para>
+ <para>
+ This procedure will help you to use Ardour to record SuperCollider's output.
+ </para>
+ <procedure>
+ <step><para>Close unnecessary applications and stop unnecessary processes, which will help to reduce the risk of a buffer underrun, which would cause an audible break in audio. If you are viewing this document in a web browser, you may want to copy-and-paste it into a simple text editor, or GEdit, if you are already using that.</para></step>
+ <step><para>Use QjackCtl to set up JACK with the right audio interface and configuration options.</para></step>
+ <step><para>In order to get a clean start, restart the SuperCollider interpreter in GEdit, then start the server.</para></step>
+ <step><para>Open Ardour with a new session, and set up the rulers and timeline as desired. Seconds is usually the most appropriate unit with which to measure a SuperCollider recording.</para></step>
+ <step><para>Add a stereo track (or however many channels desired), and rename it it "SuperCollider."</para></step>
+ <step><para>Use Ardour (the "Track/Bus Inspector" window) or QjackCtl to connect the "SuperCollider" track to SuperCollider's outputs.</para></step>
+ <step><para>You'll want to make sure that the SuperCollider output is also connected to your audio interface, so that you can hear the program as you progress. This is an example of !!multi-plexing!!. Changes to your audio interface's volume control will not affect the recording in Ardour.</para></step>
+ <step><para>Arm the track and transport in Ardour. When you are ready, start the transport. It is not important to start SuperCollider as quickly as possible, since you can cut out the silence after the recording is made.</para></step>
+ <step><para>Switch to GEdit and play the program that you want to record. If you make a mistake while starting the program, that's okay. We can always edit the recording after it's recorded.</para></step>
+ <step><para>Listen to the recording as it goes along. Use QjackCtl to make sure that you don't encounter a buffer underrun, and Ardour to make sure that you don't record a distorted signal.</para></step>
+ <step><para>When SuperCollider has finished playing your program, switch to Ardour, and stop the transport.</para></step>
+ <step><para>The audio file will be created in the "export" sub-directory of the session's directory.</para></step>
+ <step><para>When you are ready to export, use the Ardour menu: 'Session > Export > Export session to audio file'</para></step>
+ <step><para>The audio file will be created in the "export" sub-directory of the session's directory.</para></step>
+ </procedure>
+ </section>
+
+</section>
diff --git a/en-US/SuperCollider/SuperCollider.xml b/en-US/SuperCollider/SuperCollider.xml
new file mode 100644
index 0000000..0252170
--- /dev/null
+++ b/en-US/SuperCollider/SuperCollider.xml
@@ -0,0 +1,206 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM "Musicians_Guide.ent">
+%BOOK_ENTITIES;
+]>
+
+<chapter id="chap-Musicians_Guide-SuperCollider">
+ <title>SuperCollider</title>
+ <para>
+ SuperCollider is many things, but above all:
+ <itemizedlist>
+ <listitem><para>An audio synthesis engine,</para></listitem>
+ <listitem><para>A flexible programming language, and</para></listitem>
+ <listitem><para>An interpreter to transform the programming language into synthesis instructions.</para></listitem>
+ </itemizedlist>
+ </para>
+
+ <section id="sect-Musicians_Guide-SC-Technical_Convetions">
+ <title>Technical Conventions for This Chapter</title>
+ <para>
+ Because this chapter of the Musicians' Guide is more like a textbook or technical manual than a regular user manual, I have adopted several conventions commonly used in those contexts:
+ <orderedlist>
+ <listitem><para>Plural forms of technical words are written with an apostrophe (for example: Synth's instead of Synths), which helps you to know that the technical word is being used.</para></listitem>
+ <listitem><para>Plural and singular forms of technical words - in particular of language classes - are always capitalized (for example: Synth instead of synth), which helps you to differentiate between the use of the word in SuperCollider and in the real world.</para></listitem>
+ <listitem><para>Other stuff?</para></listitem>
+ </orderedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Requirements_and_Installation">
+ <title>Requirements and Installation</title>
+
+ <section id="sect-Musicians_Guide-SC-Req_and_Inst-Hardware_and_Software">
+ <title>Software and Hardware Requirements</title>
+ <para>
+ <itemizedlist>
+ <listitem><para>Planet CCRMA at Home (see [[User:Crantila/FSC/CCRMA/Everything|these instructions]])</para></listitem>
+ <listitem><para>JACK (see [[User:Crantila/FSC/Sound_Servers#Installing_JACK|these instructions]])</para></listitem>
+ <listitem><para>JACK-capable audio interface</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Req_and_Inst-Knowledge">
+ <title>Knowledge Requirements</title>
+ <para>
+ <!-- Rarely is such a warning required, but I feel it is necessary for SuperCollider -->
+ SuperCollider is by far the most difficult program described in the Fedora Musicians' Guide. The SuperCollider applications themselves are easy to use, and they work very well, but they are merely tools to help you accomplish something useful. SuperCollider has an extremely powerful and flexible programming language, with libraries designed primarily for audio processing. As often happens with computers, however, this added flexibility and power comes at the cost of requiring greater understanding and learning on the part of the user.
+
+ Because SuperCollider involves actual programming, a rudimentary understanding of some principles and concepts of computer science will provide huge benefits to somebody learning the language. The following articles from a free encyclopaedia should not be considered mandatory reading, but you should refer to them as necessary while learning the language.
+ <itemizedlist>
+ <listitem><para>[http://en.wikipedia.org/wiki/Computer_programming Computer Programming]: You probably know what this is; it's what you'll be doing.</para></listitem>
+ <listitem><para>[http://en.wikipedia.org/wiki/Programming_language Programming Language]: SuperCollider is a programming language.</para></listitem>
+ <listitem><para>[http://en.wikipedia.org/wiki/Interpreter_%28computing%29 Interpreter]: This reads your code, and sends commands to the server, which cause it to produce sound.</para></listitem>
+ <listitem><para>[http://en.wikipedia.org/wiki/Server_%28computing%29 Server]: SuperCollider has a 'server' component, which is operated by the interpreter.</para></listitem>
+ <listitem><para>[http://en.wikipedia.org/wiki/Functional_programming Functional Programming]: SuperCollider can be treated as a "functional" language.</para></listitem>
+ <listitem><para>[http://en.wikipedia.org/wiki/Imperative_programming Imperative Programming]: SuperCollider can be treated as an "imperative" language.</para></listitem>
+ <listitem><para>[http://en.wikipedia.org/wiki/Object-oriented_programming Object-oriented Programming]: SuperCollider can be treated as an "object-oriented" language.</para></listitem>
+ </itemizedlist>
+ <!-- Sourced from http://en.wikipedia.org/wiki/List_of_basic_computer_programming_topics -->
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-SC-Req_and_Inst-Available_Packages">
+ <title>Available SuperCollider Packages</title>
+ <para>
+ The SuperCollider packages are all held in the Planet CCRMA at Home repository, and there are a lot of them. Many of them have standard Fedora suffixes, but many are other kinds of optional components. Most of the optional features add libraries to SuperCollider, allowing you to use them in your audio programs. The specific features available in each additional package are not described here.
+ <itemizedlist>
+ <listitem><para>supercollider-ambiem : Optional Library ("Ambisonics classes for SC").</para></listitem>
+ <listitem><para>supercollider-debuginfo : Decodes the debugging information provided by SuperCollider.</para></listitem>
+ <listitem><para>supercollider-devel : Contains files needed for development with SuperCollider.</para></listitem>
+ <listitem><para>supercollider-dewdrop : Optional Library ("DewDrop external collection for SC").</para></listitem>
+ <listitem><para>supercollider-emacs : Adds SuperCollider support to the "emacs" text editor.</para></listitem>
+ <listitem><para>supercollider-extras : Optional Library ("Extra plugins and classes for SC").</para></listitem>
+ <listitem><para>supercollider-gedit : Adds SuperCollider support to the "gedit" text editor.</para></listitem>
+ <listitem><para>supercollider-libscsynth : "SuperCollider synthesis library."</para></listitem>
+ <listitem><para>supercollider-quarks : Optional Library ("Local quarks repository for SuperCollider").</para></listitem>
+ <listitem><para>supercollider-sclang : Help files, examples, the class library, and language interpreter.</para></listitem>
+ <listitem><para>supercollider-vim : Adds SuperCollider support to the "vim" text editor.</para></listitem>
+ <listitem><para>supercollider : Installs the "minimum requirements" to run SuperCollider.
+ <itemizedlist>
+ <listitem><para>supercollider-sclang</para></listitem>
+ <listitem><para>supercollider-libscsynth</para></listitem>
+ <listitem><para>fftw</para></listitem>
+ <listitem><para>w3m-el</para></listitem>
+ <listitem><para>emacs</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem><para>supercollider-bbcut2 : Optional Library ("Beat tracking of audio streams").</para></listitem>
+ <listitem><para>supercollider-bbcut2-debuginfo : Decodes the debugging information provided by bbcut2.</para></listitem>
+ <listitem><para>supercollider-mathlib : Optional Library ("Useful classes for SC").</para></listitem>
+ <listitem><para>supercollider-redclasses : Optional Library ("Frederik Olofsson Red SC classes").</para></listitem>
+ <listitem><para>supercollider-redclasses-debuginfo : Decodes the debugging information provided by redclasses.</para></listitem>
+ <listitem><para>supercollider-world : Installs most SuperCollider packages.
+ <itemizedlist>
+ <listitem><para>supercollider</para></listitem>
+ <listitem><para>abmiem</para></listitem>
+ <listitem><para>supercollider-redclasses</para></listitem>
+ <listitem><para>supercollider-dewdrop</para></listitem>
+ <listitem><para>supercollider-emacs</para></listitem>
+ <listitem><para>supercollider-mathlib</para></listitem>
+ <listitem><para>supercollider-midifile</para></listitem>
+ <listitem><para>supercollider-extras</para></listitem>
+ <listitem><para>supercollider-bbcut2</para></listitem>
+ <listitem><para>supercollider-reduniverse</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ <listitem><para>supercollider-midifile : Optional Library ("MIDI file reader for SuperCollider").</para></listitem>
+ <listitem><para>supercollider-reduniverse : Optional Library ("Sonification and visualization of dynamic systems").</para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Req_and_Inst-Recommended_Installation">
+ <title>Recommended Installation</title>
+ <para>
+ If you have never used SuperCollider before, then I recommend installing the smallest number of packages possible. This will allow you to start learning with the core classes, available on all SuperCollider installations. Installing the bare minimum requirements will not prevent you from installing optional libraries in the future, of course.
+ </para>
+ <para>
+ The recommended installation also avoids installing the "emacs" or "vim" components, which - unless you are already a programmer - you probably don't know how to use. The "emacs" and "vim" text editors are extremely powerful and extensible, but they can be difficult to learn. Furthermore, there's no reason to learn them just for SuperCollider, because the component for GEdit is more than sufficient.
+ </para>
+ <para>
+ To install the minimum recommended installation for SuperCollider:
+ <orderedlist>
+ <listitem><para>In a terminal, run [pre]su -c 'yum install supercollider supercollider-gedit'[/pre]</para></listitem>
+ <listitem><para>Review the proposed installation carefully. The list may be quite long, and require a large download.</para></listitem>
+ </orderedlist>
+ </para>
+ </section>
+ </section> <!-- Ends "Requirements and Installation" Section --> <!-- SC-Req_and_Inst- -->
+
+ <section id="sect-Musicians_Guide-SC-Using_GEdit">
+ <title>Using GEdit to Write and Run SuperCollider Programs</title>
+ <para>
+ The 'supercollider-gedit' package installs an extension for GEdit which allows editing and running SuperCollider code from within GEdit. There are also SuperCollider extensions for the "emacs" and "vim" text editors. This tutorial uses the GEdit extension, because it is easier to learn how to use GEdit than "vim" or "emacs."
+ </para>
+ <section id="sect-Musicians_Guide-SC-Using_GEdit-Enable_and_Configure_SCEd">
+ <title>Enable and Configure SCEd in GEdit</title>
+ <para>
+ These steps should be followed the first time that you use GEdit's SuperCollider extension.
+ </para>
+ <procedure>
+ <step><para>Start "GEdit"</para></step>
+ <step><para>Open the Preferences window (from the menu, select 'Edit > Preferences')</para></step>
+ <step><para>Choose the 'Plugins' tab, and scroll down to "Sced," then make sure that it is selected.</para></step>
+ <step><para>Click on the "Configure Plugin" button, then select a runtime folder where the SuperCollider server will store any synth sent to it during program execution. The safest place for this folder could be a sub-folder of the location where you will store your SuperCollider code.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Using_GEdit-Start_a_Server">
+ <title>Enable SuperCollider Mode and Start a Server</title>
+ <para>
+ These steps should be followed every time you open GEdit, and wish to use the SuperCollider extension.
+ </para>
+ <procedure>
+ <step><para># From the menu, select 'Tools > SuperCollider Mode'</para></step>
+ <step><para>A 'SuperCollider' menu should appear, and a window at the bottom which says, "SuperCollider output".</para></step>
+ <step><para>If you cannot see the window at the bottom, then select 'View > Bottom Pane' from the menu, so that it shows up. It is sometimes important to see the information that SuperCollider provides in this window.</para></step>
+ <step><para>After enabling SuperCollider mode, the window should display a series of notices. Near the end should be something like this:
+ [pre]RESULT = 0
+ Welcome to SuperCollider, for help type ctrl-c ctrl-h (Emacs) or :SChelp (vim) or ctrl-U (sced/gedit)[/pre]
+ If this window gives a non-zero value for "RESULT," then an error has probably occurred, and you should scroll up to see what it is, and try to fix it. If you receive the following warning: "The GUI scheme 'swing' is not installed" then you will not be able to run any SuperCollider prorams that use a GUI (graphical user interface). The GUI components are not used anywhere in this Guide, and they are highly optional.</para></step>
+ <step><para>You will probably also want to start a server at this point, so from the menu select 'SuperCollider > Start Server'.</para></step>
+ <step><para>After the server starts, you should see messages from "JackDriver". If a JACK server is not already started, then SuperCollider will start one automatically.</para></step>
+ <step><para>If the SuperCollider server started successfully, you should see a message similar to this:
+ [pre]SuperCollider 3 server ready..
+ JackDriver: max output latency 46.4 ms
+ notification is on[/pre]</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Using_GEdit-Executing_Code">
+ <title>Executing Code in GEdit</title>
+ <para>
+ You can execute code directly from GEdit, without having to use "sclang" from the command-line.
+ </para>
+ <procedure>
+ <step><para>Ensure that SuperCollider mode is enabled, and that a server has been started.</para></step>
+ <step><para>Select the code that you wish to execute. A single line of code may be executed simply by placing the text-input cursor on that line.</para></step>
+ <step><para>Press 'Ctrl+E' on the keyboard, or from the menu select 'SuperCollider > Evaluate'</para></step>
+ <step><para>To stop all sound on the server, press 'Esc' on the keyboard, or from the menu select 'SuperCollider > Stop Sound'</para></step>
+ <step><para>If the server successfully executes the code, then it will output something to the "SuperCollider output" pane. The output will be different, depending on what SuperCollider asked the server to do, but will usually either look like this: <code>Synth("temp_0": 1000)</code>, or this: <code>RESULT = 0</code>.</para></step>
+ </procedure>
+ </section>
+ <section id="sect-Musicians_Guide-SC-Using_GEdit-Other_Tips">
+ <title>Other Tips for Using GEdit with SuperCollider</title>
+ <para>
+ <itemizedlist>
+ <listitem><para>If you close GEdit while the SuperCollider server is running, then GEdit will automatically shut down the server.</para></listitem>
+ <listitem><para>If JACK is started by SuperCollider, then it will automatically terminate when the SuperCollider server terminates.</para></listitem>
+ <listitem><para>SuperCollider will automatically attempt to connect its outputs to the system's outputs. If your audio output doesn't work, then you should use "QjackCtl" to verify that it is correctly connected.</para></listitem>
+ <listitem><para>Other Functions available in the SuperCollider menu include:
+ <itemizedlist>
+ <listitem><para>Find Help (Opens the SuperCollider help file for currently-selected object).</para></listitem>
+ <listitem><para>Find Definition (Opens the SuperCollider source file for the currently-selected object).</para></listitem>
+ <listitem><para>Browse class (doesn't work for me?!?!?!?!)</para></listitem>
+ <listitem><para>Inspect Object (doesn't work for me?!?!?!?!)</para></listitem>
+ <listitem><para>Restart Interpreter (Restarts the SuperCollider interpreter; also closes running servers, but does not restart them).</para></listitem>
+ <listitem><para>Clear output (Clears all output from the "SuperCollider output" pane).</para></listitem>
+ </itemizedlist>
+ </para></listitem>
+ </itemizedlist>
+ </para>
+ </section>
+ </section> <!-- Ends the "Using GEdit" Section --> <!-- SC-Using_GEdit- -->
+
+ <!-- These link to the rest of the SuperCollider chapter -->
+ <xi:include href="SuperCollider-Basic_Programming.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="SuperCollider-Composing.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="SuperCollider-Exporting.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+</chapter>
\ No newline at end of file
Author: transif
Date: 2010-07-29 21:12:10 +0000 (Thu, 29 Jul 2010)
New Revision: 265
Modified:
community/f13/es-ES/Apache_HTTP_Server.po
Log:
l10n: Updates to Spanish (Castilian) (es) translation
Transmitted-via: Transifex (translate.fedoraproject.org)
Modified: community/f13/es-ES/Apache_HTTP_Server.po
===================================================================
--- community/f13/es-ES/Apache_HTTP_Server.po 2010-07-29 19:35:47 UTC (rev 264)
+++ community/f13/es-ES/Apache_HTTP_Server.po 2010-07-29 21:12:10 UTC (rev 265)
@@ -7,7 +7,7 @@
msgstr ""
"Project-Id-Version: Managing Confined Services\n"
"POT-Creation-Date: 2010-05-13T23:05:30\n"
-"PO-Revision-Date: 2010-07-29 12:00-0300\n"
+"PO-Revision-Date: 2010-07-29 14:47-0300\n"
"Last-Translator: Héctor Daniel Cabrera <logan(a)fedoraproject.org>\n"
"Language-Team: Fedora Spanish <trans-es(a)lists.fedoraproject.org>\n"
"MIME-Version: 1.0\n"
@@ -546,7 +546,7 @@
#. Tag: para
#, no-c-format
msgid "SELinux is based on the least level of access required for a service to run. Services can be run in a variety of ways; therefore, you must tell SELinux how you are running services. This can be achieved via Booleans that allow parts of SELinux policy to be changed at runtime, without any knowledge of SELinux policy writing. This allows changes, such as allowing services access to NFS file systems, without reloading or recompiling SELinux policy."
-msgstr "SELinux está basado en el menor de los niveles de acceso necesarios para un servicio funcione. Los servicios pueden ser ejecutados en una variedad de formas; por lo tanto debe decirle a SELinux de qué manera usted está ejecutando servicios. Esto puede ser logrado mediante los Booleanos que permiten que determinadas partes de SELinux puedan ser modificadas en el tiempo de ejecución, sin ningún tipo de conocimiento relacionado con la escritura de políticas SELinux. Esto permite cambios como permitir el acceso de los servicios a sistemas de archivos NFS, sin por ello tener que recargar o recompilar políticas de SELinux."
+msgstr "SELinux está basado en el menor de los niveles de acceso necesarios para que un servicio funcione. Los servicios pueden ser ejecutados en una variedad de formas; por lo tanto debe decirle a SELinux de qué manera usted está ejecutando servicios. Esto puede ser logrado mediante los Booleanos que permiten que determinadas partes de SELinux puedan ser modificadas en el tiempo de ejecución, sin ningún tipo de conocimiento relacionado con la escritura de políticas SELinux. Esto permite cambios como permitir el acceso de los servicios a sistemas de archivos NFS, sin por ello tener que recargar o recompilar políticas de SELinux."
#. Tag: para
#, no-c-format
Author: transif
Date: 2010-07-29 19:29:53 +0000 (Thu, 29 Jul 2010)
New Revision: 262
Modified:
community/f13/es-ES/Squid.po
Log:
l10n: Updates to Spanish (Castilian) (es) translation
Transmitted-via: Transifex (translate.fedoraproject.org)
Modified: community/f13/es-ES/Squid.po
===================================================================
--- community/f13/es-ES/Squid.po 2010-07-29 19:28:59 UTC (rev 261)
+++ community/f13/es-ES/Squid.po 2010-07-29 19:29:53 UTC (rev 262)
@@ -5,12 +5,13 @@
msgstr ""
"Project-Id-Version: 0\n"
"POT-Creation-Date: 2010-05-13T23:05:31\n"
-"PO-Revision-Date: 2010-05-13T23:05:31\n"
-"Last-Translator: Automatically generated\n"
+"PO-Revision-Date: 2010-07-29 16:11-0300\n"
+"Last-Translator: Claudio Rodrigo Pereyra Diaz <claudio(a)pereyradiaz.com.ar>\n"
"Language-Team: None\n"
"MIME-Version: 1.0\n"
-"Content-Type: application/x-publican; charset=UTF-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Spanish\n"
#. Tag: title
#, no-c-format
@@ -34,10 +35,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# yum install squid\n"
-""
msgstr ""
+"\n"
+"# yum install squid\n"
#. Tag: title
#, no-c-format
@@ -47,47 +50,54 @@
#. Tag: para
#, no-c-format
msgid "When SELinux is enabled, squid runs confined by default. Confined processes run in their own domains, and are separated from other confined processes. If a confined process is compromised by an attacker, depending on SELinux policy configuration, an attacker's access to resources and the possible damage they can do is limited. The following example demonstrates the squid processes running in their own domain. This example assumes the squid package is installed:"
-msgstr ""
+msgstr "Cuando SELinux esta habilitado, squid se ejecuta confinado por defecto. Los procesos confinados se ejecutan en su propio dominio, y están separados de otros procesos confinados. Si un proceso confinado es comprometido por un atacante, dependiendo de la configuración de políticas de SELinux, los accesos a recursos del atacante y los posibles daños que pueda causar son limitados. El siguiente ejemplo demuestra el procesos squid ejecutándose en su propio dominio. Este ejemplo asume que el paquete <package>squid</package> esta instalado:"
#. Tag: para
#, no-c-format
msgid "Run <command>getenforce</command> to confirm SELinux is running in enforcing mode:"
-msgstr ""
+msgstr "Ejecute <command>getenforce</command> para confirmar que SELinux esta corriente en modo obediente:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"$ getenforce\n"
"Enforcing\n"
-""
msgstr ""
+"\n"
+"$ getenforce\n"
+"Enforcing\n"
#. Tag: para
#, no-c-format
msgid "The <command>getenforce</command> command returns <computeroutput>Enforcing</computeroutput> when SELinux is running in enforcing mode."
-msgstr ""
+msgstr "El comando <command>getenforce</command> retorna <computeroutput>Enforcing</computeroutput> cuando SELinux está corriendo en modo obediente."
#. Tag: para
#, no-c-format
msgid "Run <command>service squid start</command> as the root user to start <systemitem class=\"daemon\">squid</systemitem>:"
-msgstr ""
+msgstr "Ejecute <command>service squid start</command> como usuario root para iniciar <systemitem class=\"daemon\">squid</systemitem>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# service squid start\n"
"Starting squid: [ OK ]\n"
-""
msgstr ""
+"\n"
+"# service squid start\n"
+"Iniciando squid: [ OK ]\n"
#. Tag: para
#, no-c-format
msgid "Run <command>ps -eZ | grep squid</command> to view the <systemitem class=\"daemon\">squid</systemitem> processes:"
-msgstr ""
+msgstr "Ejecute <command>ps -eZ | grep squid</command> para ver el proceso <systemitem class=\"daemon\">squid</systemitem>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"$ ps -eZ | grep squid\n"
"unconfined_u:system_r:squid_t:s0 2522 ? 00:00:00 squid\n"
"unconfined_u:system_r:squid_t:s0 2524 ? 00:00:00 squid\n"
@@ -97,13 +107,12 @@
"unconfined_u:system_r:squid_t:s0 2529 ? 00:00:00 ncsa_auth\n"
"unconfined_u:system_r:squid_t:s0 2530 ? 00:00:00 ncsa_auth\n"
"unconfined_u:system_r:squid_t:s0 2531 ? 00:00:00 unlinkd\n"
-""
msgstr ""
#. Tag: para
#, no-c-format
msgid "The SELinux context associated with the <systemitem class=\"daemon\">squid</systemitem> processes is <computeroutput>unconfined_u:system_r:squid_t:s0</computeroutput>. The second last part of the context, <computeroutput>squid_t</computeroutput>, is the type. A type defines a domain for processes and a type for files. In this case, the <systemitem class=\"daemon\">squid</systemitem> processes are running in the <computeroutput>squid_t</computeroutput> domain."
-msgstr ""
+msgstr "El contexto SELinux asociado con el proceso <systemitem class=\"daemon\">squid</systemitem> es <computeroutput>unconfined_u:system_r:squid_t:s0</computeroutput>. La segunda parte del contexto, <computeroutput>squid_t</computeroutput>, es el tipo. El tipo define el dominio para el proceso y tipos de archivos. En este caso, el proceso <systemitem class=\"daemon\">squid</systemitem> está corriendo en el dominio <computeroutput>squid_t</computeroutput>."
#. Tag: para
#, no-c-format
@@ -122,10 +131,10 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# service squid status\n"
"squid is stopped\n"
-""
msgstr ""
#. Tag: para
@@ -135,11 +144,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# service squid stop\n"
"Stopping squid: [ OK ]\n"
-""
msgstr ""
+"\n"
+"# service squid stop\n"
+"Parando squid: [ OK ]\n"
#. Tag: para
#, no-c-format
@@ -148,12 +160,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"semanage port -l | grep -w -i squid_port_t\n"
"squid_port_t tcp 3128, 3401, 4827\n"
"squid_port_t udp 3401, 4827\n"
"\n"
-""
msgstr ""
#. Tag: para
@@ -163,10 +175,10 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# Squid normally listens to port 3128\n"
"http_port 10000\n"
-""
msgstr ""
#. Tag: para
@@ -176,22 +188,22 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# service squid start\n"
"Starting squid: .................... [FAILED]\n"
-""
msgstr ""
#. Tag: para
#, no-c-format
msgid "An SELinux denial similar to the following is logged to <filename>/var/log/messages</filename>:"
-msgstr ""
+msgstr "También, la siguiente negación SELinux es registrada en <filename>/var/log/messages</filename>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"localhost setroubleshoot: SELinux is preventing the squid (squid_t) from binding to port 1000. For complete SELinux messages. run sealert -l 97136444-4497-4fff-a7a7-c4d8442db982\n"
-""
msgstr ""
#. Tag: para
@@ -201,9 +213,9 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# semanage port -a -t squid_port_t -p tcp 10000\n"
-""
msgstr ""
#. Tag: para
@@ -213,11 +225,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# service squid start\n"
"Starting squid: [ OK ]\n"
-""
msgstr ""
+"\n"
+"# service squid start\n"
+"Iniciando squid: [ OK ]\n"
#. Tag: para
#, no-c-format
@@ -227,22 +242,22 @@
#. Tag: title
#, no-c-format
msgid "Types"
-msgstr ""
+msgstr "Tipos"
#. Tag: para
#, no-c-format
msgid "Type Enforcement is the main permission control used in SELinux targeted policy. All files and processes are labeled with a type: types define a domain for processes and a type for files. SELinux policy rules define how types access each other, whether it be a domain accessing a type, or a domain accessing another domain. Access is only allowed if a specific SELinux policy rule exists that allows it."
-msgstr ""
+msgstr "El tipo Obediente es el principal control de permisos usado en SELinux con política por objetivo. Todos los archivos y procesos son etiquetados con un tipo: el tipo define un dominio para el proceso y los tipos para archivos. Las reglas de política de SELinux definen que tipos tiene acceso unos con otros, se trate de un dominio accediendo a un tipo, o a un dominio accediendo a otro dominio. El acceso solo es permitido si existe una política SELinux específica que permita eso."
#. Tag: para
#, no-c-format
msgid "The following types are used with <systemitem class=\"daemon\">squid</systemitem>. Different types allow you to configure flexible access:"
-msgstr ""
+msgstr "El siguiente tipo es usado con <systemitem class=\"daemon\">squid</systemitem>. Los diferentes tipos le permiten configurar accesos flexibles:"
#. Tag: term
#, no-c-format
msgid "<computeroutput>httpd_squid_script_exec_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>httpd_squid_script_exec_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -252,7 +267,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_cache_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_exec_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -262,7 +277,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_conf_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_exec_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -272,17 +287,17 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_exec_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_exec_t</computeroutput>"
#. Tag: para
#, no-c-format
msgid "This type is used for the squid binary, <filename>/usr/sbin/squid</filename>."
-msgstr ""
+msgstr "Este tipo es usado por los binarios en <filename>/usr/sbin/squid</filename>"
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_log_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_var_run_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -292,7 +307,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_initrc_exec_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_var_run_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -302,7 +317,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_var_run_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_var_run_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -312,17 +327,17 @@
#. Tag: title
#, no-c-format
msgid "Booleans"
-msgstr ""
+msgstr "Booleanos"
#. Tag: para
#, no-c-format
msgid "SELinux is based on the least level of access required for a service to run. Services can be run in a variety of ways; therefore, you must tell SELinux how you are running services. The following Boolean allows you to tell SELinux how you are running Squid:"
-msgstr ""
+msgstr "SELinux se basa en el menor nivel de acceso requerido por un servicio para ser ejecutado. Los servicios pueden ejecutarse en una variedad de formas; por lo tanto, debe indicarle a SELinux como esta corriendo usted los servicios. Los siguientes Booleanos le permiten a usted indicarle a SELinux como está ejecutando Squid:"
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_connect_any</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_use_tproxy</computeroutput>"
#. Tag: para
#, no-c-format
@@ -332,7 +347,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>squid_use_tproxy</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>squid_use_tproxy</computeroutput>"
#. Tag: para
#, no-c-format
@@ -342,7 +357,7 @@
#. Tag: title
#, no-c-format
msgid "Configuration Examples"
-msgstr ""
+msgstr "Ejemplos de configuración"
#. Tag: title
#, no-c-format
@@ -371,10 +386,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"cache_dir ufs /var/spool/squid 100 16 256\n"
-""
msgstr ""
+"\n"
+"cache_dir ufs /var/spool/squid 100 16 256\n"
#. Tag: para
#, no-c-format
@@ -393,10 +410,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"visible_hostname squid.example.com\n"
-""
msgstr ""
+"\n"
+"visible_hostname squid.example.com\n"
#. Tag: para
#, no-c-format
@@ -405,11 +424,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# /sbin/service squid start\n"
"init_cache_dir /var/spool/squid... Starting squid: . [ OK ]\n"
-""
msgstr ""
+"\n"
+"# /sbin/service squid start\n"
+"init_cache_dir /var/spool/squid... Inciando squid: . [ OK ]\n"
#. Tag: para
#, no-c-format
@@ -418,11 +440,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# ls -lZ /var/run/squid.pid \n"
"-rw-r--r--. root squid unconfined_u:object_r:<emphasis>squid_var_run_t</emphasis>:s0 /var/run/squid.pid\n"
-""
msgstr ""
+"\n"
+"# ls -lZ /var/run/squid.pid \n"
+"-rw-r--r--. root squid unconfined_u:object_r:<emphasis>squid_var_run_t</emphasis>:s0 /var/run/squid.pid\n"
#. Tag: para
#, no-c-format
@@ -436,10 +461,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"SELinux is preventing the squid daemon from connecting to network port 10000\n"
-""
msgstr ""
+"\n"
+"SELinux está previniendo acerca de la intención del demonio squid de conectarse al puerto de red 10000\n"
#. Tag: para
#, no-c-format
@@ -449,7 +476,7 @@
#. Tag: screen
#, no-c-format
msgid "# setsebool -P squid_connect_any on"
-msgstr ""
+msgstr "# setsebool -P squid_connect_any on"
#. Tag: para
#, no-c-format
Author: transif
Date: 2010-07-29 19:28:59 +0000 (Thu, 29 Jul 2010)
New Revision: 261
Modified:
community/f13/es-ES/PostgreSQL.po
Log:
l10n: Updates to Spanish (Castilian) (es) translation
Transmitted-via: Transifex (translate.fedoraproject.org)
Modified: community/f13/es-ES/PostgreSQL.po
===================================================================
--- community/f13/es-ES/PostgreSQL.po 2010-07-29 19:28:00 UTC (rev 260)
+++ community/f13/es-ES/PostgreSQL.po 2010-07-29 19:28:59 UTC (rev 261)
@@ -5,17 +5,18 @@
msgstr ""
"Project-Id-Version: 0\n"
"POT-Creation-Date: 2010-05-13T23:05:31\n"
-"PO-Revision-Date: 2010-05-13T23:05:31\n"
-"Last-Translator: Automatically generated\n"
+"PO-Revision-Date: 2010-07-29 16:20-0300\n"
+"Last-Translator: Claudio Rodrigo Pereyra Diaz <claudio(a)pereyradiaz.com.ar>\n"
"Language-Team: None\n"
"MIME-Version: 1.0\n"
-"Content-Type: application/x-publican; charset=UTF-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Spanish\n"
#. Tag: title
#, no-c-format
msgid "PostgreSQL"
-msgstr ""
+msgstr "PostgreSQL"
#. Tag: para
#, no-c-format
@@ -30,19 +31,21 @@
#. Tag: para
#, no-c-format
msgid "In Fedora, the <package>postgresql-server</package> package provides PostgreSQL. Run <command>rpm -q postgresql-server</command> to see if the <package>postgresql-server</package> package is installed. If it is not installed, run the following command as the root user to install it:"
-msgstr ""
+msgstr "En Fedora, el paquete <package>postgresql-server</package> provee PostgreSQL. Ejecute <command>rpm -q postgresql-server</command> para ver si el paquete <package>postgresql-server</package> está instalado. Si no esta instalado, ejecute el siguiente comando como usuario root para instarlo:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"yum install postgresql-server\n"
-""
msgstr ""
+"\n"
+"yum install postgresql-server\n"
#. Tag: title
#, no-c-format
msgid "PostgreSQL and SELinux"
-msgstr ""
+msgstr "PostgreSQL y SELinux"
#. Tag: para
#, no-c-format
@@ -52,42 +55,49 @@
#. Tag: para
#, no-c-format
msgid "Run <command>getenforce</command> to confirm SELinux is running in enforcing mode:"
-msgstr ""
+msgstr "Ejecute <command>getenforce</command> para confirmar que SELinux esta corriente en modo obediente:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"$ getenforce\n"
"Enforcing\n"
-""
msgstr ""
+"\n"
+"$ getenforce\n"
+"Enforcing\n"
#. Tag: para
#, no-c-format
msgid "The <command>getenforce</command> command returns <computeroutput>Enforcing</computeroutput> when SELinux is running in enforcing mode."
-msgstr ""
+msgstr "El comando <command>getenforce</command> retorna <computeroutput>Enforcing</computeroutput> cuando SELinux está corriendo en modo obediente."
#. Tag: para
#, no-c-format
msgid "Run <command>service postgresql start</command> as the root user to start <systemitem class=\"daemon\">postgresql</systemitem>:"
-msgstr ""
+msgstr "Ejecute <command>service postgresql start</command> como usuario root para iniciar <systemitem class=\"daemon\">postgresql</systemitem>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"service postgresql start\n"
"Starting postgresql service: [ OK ]\n"
-""
msgstr ""
+"\n"
+"# service postgresql start\n"
+"Iniciando postgresql: [ OK ]\n"
#. Tag: para
#, no-c-format
msgid "Run <command>ps -eZ | grep postgres</command> to view the <systemitem class=\"daemon\">postgresql</systemitem> processes:"
-msgstr ""
+msgstr "Ejecute <command>ps -eZ | grep postgresql</command> para ver el proceso <systemitem class=\"daemon\">postgresql</systemitem>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"ps -eZ | grep postgres\n"
"unconfined_u:system_r:postgresql_t:s0 395 ? 00:00:00 postmaster\n"
"unconfined_u:system_r:postgresql_t:s0 397 ? 00:00:00 postmaster\n"
@@ -95,33 +105,40 @@
"unconfined_u:system_r:postgresql_t:s0 400 ? 00:00:00 postmaster\n"
"unconfined_u:system_r:postgresql_t:s0 401 ? 00:00:00 postmaster\n"
"unconfined_u:system_r:postgresql_t:s0 402 ? 00:00:00 postmaster\n"
-""
msgstr ""
+"\n"
+"ps -eZ | grep postgres\n"
+"unconfined_u:system_r:postgresql_t:s0 395 ? 00:00:00 postmaster\n"
+"unconfined_u:system_r:postgresql_t:s0 397 ? 00:00:00 postmaster\n"
+"unconfined_u:system_r:postgresql_t:s0 399 ? 00:00:00 postmaster\n"
+"unconfined_u:system_r:postgresql_t:s0 400 ? 00:00:00 postmaster\n"
+"unconfined_u:system_r:postgresql_t:s0 401 ? 00:00:00 postmaster\n"
+"unconfined_u:system_r:postgresql_t:s0 402 ? 00:00:00 postmaster\n"
#. Tag: para
#, no-c-format
msgid "The SELinux context associated with the <systemitem class=\"daemon\">postgresql</systemitem> processes is <computeroutput>unconfined_u:system_r:postgresql_t:s0</computeroutput>. The second last part of the context, <computeroutput>postgresql_t</computeroutput>, is the type. A type defines a domain for processes and a type for files. In this case, the <systemitem class=\"daemon\">postgresql</systemitem> processes are running in the <computeroutput>postgresql_t</computeroutput> domain."
-msgstr ""
+msgstr "El contexto SELinux asociado con el proceso <systemitem class=\"daemon\">postgresql</systemitem> es <computeroutput>unconfined_u:system_r:postgresql_t:s0</computeroutput>. La segunda parte del contexto, <computeroutput>postgresql_t</computeroutput>, es el tipo. El tipo define el dominio para el proceso y tipos de archivos. En este caso, el proceso <systemitem class=\"daemon\">postgresql</systemitem> está corriendo en el dominio postgresql_t."
#. Tag: title
#, no-c-format
msgid "Types"
-msgstr ""
+msgstr "Tipos"
#. Tag: para
#, no-c-format
msgid "Type Enforcement is the main permission control used in SELinux targeted policy. All files and processes are labeled with a type: types define a domain for processes and a type for files. SELinux policy rules define how types access each other, whether it be a domain accessing a type, or a domain accessing another domain. Access is only allowed if a specific SELinux policy rule exists that allows it."
-msgstr ""
+msgstr "El tipo Obediente es el principal control de permisos usado en SELinux con política por objetivo. Todos los archivos y procesos son etiquetados con un tipo: el tipo define un dominio para el proceso y los tipos para archivos. Las reglas de política de SELinux definen que tipos tiene acceso unos con otros, se trate de un dominio accediendo a un tipo, o a un dominio accediendo a otro dominio. El acceso solo es permitido si existe una política SELinux específica que permita eso."
#. Tag: para
#, no-c-format
msgid "The following types are used with <systemitem class=\"daemon\">postgresql</systemitem>. Different types allow you to configure flexible access:"
-msgstr ""
+msgstr "El siguiente tipo es usado con <systemitem class=\"daemon\">postgresql</systemitem>. Los diferentes tipos le permiten configurar accesos flexibles:"
#. Tag: term
#, no-c-format
msgid "<computeroutput>postgresql_db_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postgresql_db_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -131,27 +148,27 @@
#. Tag: para
#, no-c-format
msgid "<filename>/usr/lib/pgsql/test/regres</filename>"
-msgstr ""
+msgstr "<filename>/usr/lib/pgsql/test/regres</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/usr/share/jonas/pgsql</filename>"
-msgstr ""
+msgstr "<filename>/usr/share/jonas/pgsql</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/lib/pgsql/data</filename>"
-msgstr ""
+msgstr "<filename>/var/lib/pgsql/data</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/lib/postgres(ql)?</filename>"
-msgstr ""
+msgstr "<filename>/var/lib/postgres(ql)?</filename>"
#. Tag: term
#, no-c-format
msgid "<computeroutput>postgresql_etc_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postgresql_etc_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -161,7 +178,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>postgresql_exec_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postgresql_exec_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -171,27 +188,27 @@
#. Tag: para
#, no-c-format
msgid "<filename>/usr/bin/initdb(.sepgsql)?</filename>"
-msgstr ""
+msgstr "<filename>/usr/bin/initdb(.sepgsql)?</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/usr/bin/(se)?postgres</filename>"
-msgstr ""
+msgstr "<filename>/usr/bin/(se)?postgres</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/usr/lib(64)?/postgresql/bin/.*</filename>"
-msgstr ""
+msgstr "<filename>/usr/lib(64)?/postgresql/bin/.*</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/usr/lib/phsql/test/regress/pg_regress</filename>"
-msgstr ""
+msgstr "<filename>/usr/lib/phsql/test/regress/pg_regress</filename>"
#. Tag: term
#, no-c-format
msgid "<computeroutput>postgresql_initrc_exec_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postgresql_initrc_exec_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -201,7 +218,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>postgresql_log_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postgresql_log_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -211,42 +228,42 @@
#. Tag: para
#, no-c-format
msgid "<filename>/var/lib/pgsql/logfile</filename>"
-msgstr ""
+msgstr "<filename>/var/lib/pgsql/logfile</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/lib/pgsql/pgstartup.log</filename>"
-msgstr ""
+msgstr "<filename>/var/lib/pgsql/pgstartup.log</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/lib/sepgsql/pgstartup.log</filename>"
-msgstr ""
+msgstr "<filename>/var/lib/sepgsql/pgstartup.log</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/log/postgresql</filename>"
-msgstr ""
+msgstr "<filename>/var/log/postgresql</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/log/postgres.log.*</filename>"
-msgstr ""
+msgstr "<filename>/var/log/postgres.log.*</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/log/rhdb/rhdb</filename>"
-msgstr ""
+msgstr "<filename>/var/log/rhdb/rhdb</filename>"
#. Tag: para
#, no-c-format
msgid "<filename>/var/log/sepostgresql.log.*</filename>"
-msgstr ""
+msgstr "<filename>/var/log/sepostgresql.log.*</filename>"
#. Tag: term
#, no-c-format
msgid "<computeroutput>postgresql_var_run_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postgresql_var_run_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -256,17 +273,17 @@
#. Tag: title
#, no-c-format
msgid "Booleans"
-msgstr ""
+msgstr "Booleanos"
#. Tag: para
#, no-c-format
msgid "SELinux is based on the least level of access required for a service to run. Services can be run in a variety of ways; therefore, you must tell SELinux how you are running services. The following Boolean allows you to tell SELinux how you are running PostgreSQL:"
-msgstr ""
+msgstr "SELinux se basa en el menor nivel de acceso requerido por un servicio para ser ejecutado. Los servicios pueden ejecutarse en una variedad de formas; por lo tanto, debe indicarle a SELinux como esta corriendo usted los servicios. Los siguientes Booleanos le permiten a usted indicarle a SELinux como está ejecutando PostgreSQL:"
#. Tag: term
#, no-c-format
msgid "<computeroutput>allow_user_postgresql_connect</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>allow_user_postgresql_connect</computeroutput>"
#. Tag: para
#, no-c-format
@@ -276,12 +293,12 @@
#. Tag: title
#, no-c-format
msgid "Configuration Examples"
-msgstr ""
+msgstr "Ejemplos de configuración"
#. Tag: title
#, no-c-format
msgid "PostgreSQL Changing Database Location"
-msgstr ""
+msgstr "Cambiando la ubicación de la Base de Datos PostgreSQL"
#. Tag: para
#, no-c-format
@@ -291,7 +308,7 @@
#. Tag: para
#, no-c-format
msgid "The area where the database is located can be changed depending on individual environment requirements or preferences, however it is important that SELinux is aware of this new location - that it is labeled accordingly. This example explains how to change the location of a PostgreSQL database and then how to label the new location so that SELinux can still provide its protection mechanisms to the new area based on its contents."
-msgstr ""
+msgstr "El área donde esta ubicada la base de datos puede ser cambiada dependiendo los requerimientos o preferencias de entorno individuales, de todas formas es importante que SELinux esté consiente de la nueva ubicación, para lo cual se usa el etiquetado. Este ejemplo explica como cambiar la ubicación de la base de datos PostgreSQL y luego como etiquetar la nueva ubicación para que SELinux siga proveyendo sus mecanismos de protección para la nueva área basado en su contenido."
#. Tag: para
#, no-c-format
@@ -305,16 +322,19 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# ls -lZ /var/lib/pgsql\n"
"drwx------. postgres postgres system_u:object_r:<emphasis>postgresql_db_t</emphasis>:s0 data\n"
-""
msgstr ""
+"\n"
+"# ls -lZ /var/lib/pgsql\n"
+"drwx------. postgres postgres system_u:object_r:<emphasis>postgresql_db_t</emphasis>:s0 data\n"
#. Tag: para
#, no-c-format
msgid "This shows <computeroutput>postgresql_db_t</computeroutput> which is the default context element for the location of database files. This context will have to be manually applied to the new database location that will be used in this example in order for it to function properly."
-msgstr ""
+msgstr "Esto muestra <computeroutput>postgresql_db_t</computeroutput> lo cual es el elemento de contexto por defecto para la ubicación de los archivos de base de datos. Este contexto tendrá que ser aplicado manualmente a la nueva ubicación de la base de datos que se utilizarán en este ejemplo con el fin de asegurar su buen funcionamiento."
#. Tag: para
#, no-c-format
@@ -323,10 +343,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# mkdir -p /opt/postgresql/data\n"
-""
msgstr ""
+"\n"
+"# mkdir -p /opt/postgresql/data\n"
#. Tag: para
#, no-c-format
@@ -335,11 +357,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# ls -lZ /opt/postgresql/\n"
"drwxr-xr-x. root root unconfined_u:object_r:<emphasis>usr_t</emphasis>:s0 data\n"
-""
msgstr ""
+"\n"
+"# ls -lZ /opt/postgresql/\n"
+"drwxr-xr-x. root root unconfined_u:object_r:<emphasis>usr_t</emphasis>:s0 data\n"
#. Tag: para
#, no-c-format
@@ -348,10 +373,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# chown -R postgres:postgres /opt/postgresql\n"
-""
msgstr ""
+"\n"
+"# chown -R postgres:postgres /opt/postgresql\n"
#. Tag: para
#, no-c-format
@@ -360,12 +387,16 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# vi /etc/rc.d/init.d/postgresql\n"
"PGDATA=/opt/postgresql/data\n"
"PGLOG=/opt/postgresql/data/pgstartup.log\n"
-""
msgstr ""
+"\n"
+"# vi /etc/rc.d/init.d/postgresql\n"
+"PGDATA=/opt/postgresql/data\n"
+"PGLOG=/opt/postgresql/data/pgstartup.log\n"
#. Tag: para
#, no-c-format
@@ -379,10 +410,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"su - postgres -c "initdb -D /opt/postgresql/data"\n"
-""
msgstr ""
+"\n"
+"su - postgres -c "initdb -D /opt/postgresql/data"\n"
#. Tag: para
#, no-c-format
@@ -391,36 +424,44 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"semanage fcontext -a -t postgresql_db_t "/opt/postgresql(/.*)?"\n"
-""
msgstr ""
+"\n"
+"semanage fcontext -a -t postgresql_db_t "/opt/postgresql(/.*)?"\n"
#. Tag: para
#, no-c-format
msgid "This mapping is written to the <filename>/etc/selinux/targeted/contexts/files/file_contexts.local</filename> file:"
-msgstr ""
+msgstr "Este mapeo es escrito en el archivo <filename>/etc/selinux/targeted/contexts/files/file_contexts.local</filename>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# grep -i postgresql /etc/selinux/targeted/contexts/files/file_contexts.local\n"
"\n"
"/opt/postgresql(/.*)? system_u:object_r:postgresql_db_t:s0\n"
-""
msgstr ""
+"\n"
+"# grep -i postgresql /etc/selinux/targeted/contexts/files/file_contexts.local\n"
+"\n"
+"/opt/postgresql(/.*)? system_u:object_r:postgresql_db_t:s0\n"
#. Tag: para
#, no-c-format
msgid "Now use the <filename>restorecon</filename> command to apply this context mapping to the running system:"
-msgstr ""
+msgstr "Ahora use el comando <filename>restorecon</filename> para aplicar este mapeo de contexto al sistema en ejecución:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"restorecon -R -v /opt/postgresql\n"
-""
msgstr ""
+"\n"
+"restorecon -R -v /opt/postgresql\n"
#. Tag: para
#, no-c-format
@@ -429,11 +470,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# service postgresql start\n"
"Starting postgreSQL service: [ OK ]\n"
-""
msgstr ""
+"\n"
+"# service postgresql start\n"
+"Iniciando postgreSQL: [ OK ]\n"
#. Tag: para
#, no-c-format
@@ -442,11 +486,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"ls -lZ /opt\n"
"drwxr-xr-x. root root system_u:object_r:<emphasis>postgresql_db_t</emphasis>:s0 postgresql\n"
-""
msgstr ""
+"\n"
+"ls -lZ /opt\n"
+"drwxr-xr-x. root root system_u:object_r:<emphasis>postgresql_db_t</emphasis>:s0 postgresql\n"
#. Tag: para
#, no-c-format
@@ -455,15 +502,19 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# ps aux | grep -i postmaster\n"
"\n"
"postgres 21564 0.3 0.3 42308 4032 ? S 10:13 0:00 /usr/bin/postmaster -p 5432 -D <emphasis>/opt/postgresql/data</emphasis>\n"
-""
msgstr ""
+"\n"
+"# ps aux | grep -i postmaster\n"
+"\n"
+"postgres 21564 0.3 0.3 42308 4032 ? S 10:13 0:00 /usr/bin/postmaster -p 5432 -D <emphasis>/opt/postgresql/data</emphasis>\n"
#. Tag: para
#, no-c-format
msgid "The location has been changed and labeled, and the <systemitem class=\"daemon\">postgresql</systemitem> daemon has started successfully. At this point all running services should be tested to confirm normal operation."
-msgstr ""
+msgstr "La ubicación ha sido cambiada y etiquetada, y el demonio <systemitem class=\"daemon\">postgresql</systemitem> se ha reiniciado satisfactoriamente. A este punto todos los servicios ejecutándose deberían estar probados confirmando la operación normal."
Author: transif
Date: 2010-07-29 19:28:00 +0000 (Thu, 29 Jul 2010)
New Revision: 260
Modified:
community/f13/es-ES/Postfix.po
Log:
l10n: Updates to Spanish (Castilian) (es) translation
Transmitted-via: Transifex (translate.fedoraproject.org)
Modified: community/f13/es-ES/Postfix.po
===================================================================
--- community/f13/es-ES/Postfix.po 2010-07-29 18:59:56 UTC (rev 259)
+++ community/f13/es-ES/Postfix.po 2010-07-29 19:28:00 UTC (rev 260)
@@ -5,22 +5,23 @@
msgstr ""
"Project-Id-Version: 0\n"
"POT-Creation-Date: 2010-05-13T23:05:31\n"
-"PO-Revision-Date: 2010-05-13T23:05:31\n"
-"Last-Translator: Automatically generated\n"
+"PO-Revision-Date: 2010-07-29 16:24-0300\n"
+"Last-Translator: Claudio Rodrigo Pereyra Diaz <claudio(a)pereyradiaz.com.ar>\n"
"Language-Team: None\n"
"MIME-Version: 1.0\n"
-"Content-Type: application/x-publican; charset=UTF-8\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Spanish\n"
#. Tag: title
#, no-c-format
msgid "Postfix"
-msgstr ""
+msgstr "Postfix"
#. Tag: para
#, no-c-format
msgid "From the <ulink url=\"http://www.postfix.org/\">Postfix</ulink> project page:"
-msgstr ""
+msgstr "Fuente página del proyecto <ulink url=\"http://www.postfix.org/\">Postfix</ulink>:"
#. Tag: para
#, no-c-format
@@ -30,19 +31,21 @@
#. Tag: para
#, no-c-format
msgid "In Fedora, the <package>postfix</package> package provides postfix. Run <command>rpm -q postfix</command> to see if the <package>postfix</package> package is installed. If it is not installed, run the following command as the root user to install it:"
-msgstr ""
+msgstr "En Fedora, el paquete <package>postfix</package> provee postfix. Ejecute <command>rpm -q postfix</command> para ver si el paquete <package>postfix</package> está instalado. Si no esta instalado, ejecute el siguiente comando como usuario root para instarlo:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"yum install postfix\n"
-""
msgstr ""
+"\n"
+"yum install postfix\n"
#. Tag: title
#, no-c-format
msgid "Postfix and SELinux"
-msgstr ""
+msgstr "Postfix y SELinux"
#. Tag: para
#, no-c-format
@@ -52,48 +55,59 @@
#. Tag: para
#, no-c-format
msgid "Run <command>getenforce</command> to confirm SELinux is running in enforcing mode:"
-msgstr ""
+msgstr "Ejecute <command>getenforce</command> para confirmar que SELinux esta corriente en modo obediente:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"$ getenforce\n"
"Enforcing\n"
-""
msgstr ""
+"\n"
+"$ getenforce\n"
+"Enforcing\n"
#. Tag: para
#, no-c-format
msgid "The <command>getenforce</command> command returns <computeroutput>Enforcing</computeroutput> when SELinux is running in enforcing mode."
-msgstr ""
+msgstr "El comando <command>getenforce</command> retorna <computeroutput>Enforcing</computeroutput> cuando SELinux está corriendo en modo obediente."
#. Tag: para
#, no-c-format
msgid "Run <command>service postfix start</command> as the root user to start <systemitem class=\"daemon\">postfix</systemitem>:"
-msgstr ""
+msgstr "Ejecute <command>service postfix start</command> como usuario root para iniciar <systemitem class=\"daemon\">postfix</systemitem>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"service postfix start\n"
"Starting postfix: [ OK ]\n"
-""
msgstr ""
+"\n"
+"service postfix start\n"
+"Iniciando postfix: [ OK ]\n"
#. Tag: para
#, no-c-format
msgid "Run <command>ps -eZ | grep postfix</command> to view the <systemitem class=\"daemon\">postfix</systemitem> processes:"
-msgstr ""
+msgstr "Ejecute <command>ps -eZ | grep postfix</command> para ver el proceso <systemitem class=\"daemon\">postfix</systemitem>:"
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"ps -eZ | grep postfix\n"
"system_u:system_r:postfix_master_t:s0 1651 ? 00:00:00 master\n"
"system_u:system_r:postfix_pickup_t:s0 1662 ? 00:00:00 pickup\n"
"system_u:system_r:postfix_qmgr_t:s0 1663 ? 00:00:00 qmgr\n"
-""
msgstr ""
+"\n"
+"ps -eZ | grep postfix\n"
+"system_u:system_r:postfix_master_t:s0 1651 ? 00:00:00 master\n"
+"system_u:system_r:postfix_pickup_t:s0 1662 ? 00:00:00 pickup\n"
+"system_u:system_r:postfix_qmgr_t:s0 1663 ? 00:00:00 qmgr\n"
#. Tag: para
#, no-c-format
@@ -103,12 +117,12 @@
#. Tag: title
#, no-c-format
msgid "Types"
-msgstr ""
+msgstr "Tipos"
#. Tag: para
#, no-c-format
msgid "Type Enforcement is the main permission control used in SELinux targeted policy. All files and processes are labeled with a type: types define a domain for processes and a type for files. SELinux policy rules define how types access each other, whether it be a domain accessing a type, or a domain accessing another domain. Access is only allowed if a specific SELinux policy rule exists that allows it."
-msgstr ""
+msgstr "El tipo Obediente es el principal control de permisos usado en SELinux con política por objetivo. Todos los archivos y procesos son etiquetados con un tipo: el tipo define un dominio para el proceso y los tipos para archivos. Las reglas de política de SELinux definen que tipos tiene acceso unos con otros, se trate de un dominio accediendo a un tipo, o a un dominio accediendo a otro dominio. El acceso solo es permitido si existe una política SELinux específica que permita eso."
#. Tag: para
#, no-c-format
@@ -118,7 +132,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>postfix_etc_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postfix_etc_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -128,7 +142,7 @@
#. Tag: term
#, no-c-format
msgid "<computeroutput>postfix_data_t</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>postfix_data_t</computeroutput>"
#. Tag: para
#, no-c-format
@@ -142,25 +156,27 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"$ grep postfix /etc/selinux/targeted/contexts/files/file_contexts\n"
-""
msgstr ""
+"\n"
+"$ grep postfix /etc/selinux/targeted/contexts/files/file_contexts\n"
#. Tag: title
#, no-c-format
msgid "Booleans"
-msgstr ""
+msgstr "Booleanos"
#. Tag: para
#, no-c-format
msgid "SELinux is based on the least level of access required for a service to run. Services can be run in a variety of ways; therefore, you must tell SELinux how you are running services. The following Boolean allows you to tell SELinux how you are running Postfix:"
-msgstr ""
+msgstr "SELinux se basa en el menor nivel de acceso requerido por un servicio para ser ejecutado. Los servicios pueden ejecutarse en una variedad de formas; por lo tanto, debe indicarle a SELinux como esta corriendo usted los servicios. Los siguientes Booleanos le permiten a usted indicarle a SELinux como está ejecutando Postfix:"
#. Tag: term
#, no-c-format
msgid "<computeroutput>allow_postfix_local_write_mail_spool</computeroutput>"
-msgstr ""
+msgstr "<computeroutput>allow_postfix_local_write_mail_spool</computeroutput>"
#. Tag: para
#, no-c-format
@@ -170,12 +186,12 @@
#. Tag: title
#, no-c-format
msgid "Configuration Examples"
-msgstr ""
+msgstr "Ejemplos de configuración"
#. Tag: title
#, no-c-format
msgid "SpamAssassin and Postfix"
-msgstr ""
+msgstr "SpamAssassin y Postfix"
#. Tag: para
#, no-c-format
@@ -194,10 +210,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"yum install spamassassin\n"
-""
msgstr ""
+"\n"
+"yum install spamassassin\n"
#. Tag: para
#, no-c-format
@@ -221,11 +239,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# semanage port -l | grep spamd\n"
"spamd_port_t tcp 783\n"
-""
msgstr ""
+"\n"
+"# semanage port -l | grep spamd\n"
+"spamd_port_t tcp 783\n"
#. Tag: para
#, no-c-format
@@ -239,11 +260,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# Options to spamd\n"
"SPAMDOPTIONS="-d -p 10000 -c m5 -H"\n"
-""
msgstr ""
+"\n"
+"# Options to spamd\n"
+"SPAMDOPTIONS="-d -p 10000 -c m5 -H"\n"
#. Tag: para
#, no-c-format
@@ -257,14 +281,14 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"/etc/init.d/spamassassin start\n"
"Starting spamd: [2203] warn: server socket setup failed, retry 1: spamd: could not create INET socket on 127.0.0.1:10000: Permission denied\n"
"[2203] warn: server socket setup failed, retry 2: spamd: could not create INET socket on 127.0.0.1:10000: Permission denied\n"
"[2203] error: spamd: could not create INET socket on 127.0.0.1:10000: Permission denied\n"
"spamd: could not create INET socket on 127.0.0.1:10000: Permission denied\n"
" [FAILED]\n"
-""
msgstr ""
#. Tag: para
@@ -279,10 +303,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"SELinux is preventing the spamd (spamd_t) from binding to port 10000.\n"
-""
msgstr ""
+"\n"
+"SELinux está previniendo acerca de la intención del demonio spamd de conectarse al puerto de red 10000\n"
#. Tag: para
#, no-c-format
@@ -291,10 +317,12 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"semanage port -a -t spamd_port_t -p tcp 10000\n"
-""
msgstr ""
+"\n"
+"semanage port -a -t spamd_port_t -p tcp 10000\n"
#. Tag: para
#, no-c-format
@@ -303,13 +331,13 @@
#. Tag: screen
#, no-c-format
-msgid "\n"
+msgid ""
+"\n"
"# /etc/init.d/spamassassin start\n"
"Starting spamd: [ OK ]\n"
"\n"
"# netstat -lnp | grep 10000\n"
"tcp 0 0 127.0.0.1:10000 0.0.0.0:* LISTEN 2224/spamd.pid\n"
-""
msgstr ""
#. Tag: para