.. _gettingStartedBlocksDoc: .. index:: single: Example; Blocks, Ports, and Properties ============================= Blocks, Ports, and Properties ============================= Let's get right to it with some examples. The following code is the simplest program in Stride. :: # Load platform version 0.0 on target version 0.0 use Platform version 0.0 on Hardware version 0.0 # Stream audio input 1 to audio output 1 AudioIn[1] >> AudioOut[1]; The program streams an audio signal from audio input 1 (mono) to audio output 1 (mono). Audio input 1 and audio output 1 are physical plugs on the target hardware. Every Stride code starts with a "``use PLATFORM version VERSION on HARDWARE version VERSION``" expression. It tells Stride which :ref:`platform descriptor file ` to load. The platform descriptor file contains information related to resource abstraction and functionality. "``AudioIn[1] >> AudioOut[1]``" is a **stream expression**. 'AudioIn' and 'AudioOut' are **labels** representing two **Stride block bundles**. They are both declared in the platform descriptor file and they abstract the underlying harware inputs and outputs. Stride has many block types. One of these block types is :ref:`signal `. Stride allows bundling blocks together. ``AudioIn[1]`` and ``AudioOut[1]`` are the first blocks in the block bunldes. Connections between blocks can be created using the **stream operator** ``>>``. For an expression to be called a stream expression, it must contain at least one stream operator. All stream exprssions must end with a **semicolons**. Connections between Stride blocks happens through **ports**. A port has a **direction**, and a **type**. A port can have two possible :ref:`port directions `: **input** or **output**. A signal block, for instance, has six ports: Five input ports and one output port. A port can be one of these :ref:`port types `. It can also be a hybrid port. .. figure:: ../blocksCore/Images/SignalBlock.png :scale: 100% :alt: Signal Block :align: center **Figure: Signal Block** Ports in Stride are exposed in one of two ways, either through the block label or through properties. Connections with ports exposed through the block label are achieved using the stream operator or property assignments during other while connections with ports exposed through a property are done during a block declaration. In case of a signal block, its label exposes the `hybrid stream` input port and the `hybrid stream` output port. In the expression "``AudioIn[1] >> AudioOut[1]``", since the label 'AudioIn[1]' is on the left hand side of the stream operator, it represents the `hybrid stream` output port of the ``AudioIn[1]`` signal block while the label 'AudioOut[1]' represents the `hybrid stream` input port of the ``AudioOut[1]`` signal block since it is on the right hand side. In order to establish a connection and stream between an output port and an input port, their types should match or a conversion between their types should be defined in the language. The stream operator can only connect ports exposed by the label. **In the case of a signal block the output port can connect to multiple input ports but its input port can only connect to a single output port.** The `hybrid stream` input port of ``AudioIn[1]`` is connected to an audio hardware resource (Analog to Digital Converter). The port cannot accept any other connections. The `hybrid stream` output port of ``AudioIn[1]`` can connect and stream to `hybrid stream` input ports. In the preceding example, the `hybrid stream` output port of ``AudioIn[1]`` is connected to the `hybrid stream` input port of ``AudioOut[1]``. Although the `hybrid stream` output port of ``AudioIn[1]`` is capable of establishing other connections, no such connections are made. The `hybrid stream` output port of ``AudioOut[1]`` is connected to an audio hardware resource (Digital to Analog Converter) and can connect and stream to other `hybrid stream` input ports. In the preceding example, no such connections are made. The `hybrid stream` input port of ``AudioOut[1]`` is connected to the `hybrid stream` output port of ``AudioIn[1]``. No further connections can be made to the `hybrid stream` input port of ``AudioOut[1]``. Identifiers, like 'AudioIn[1]' and 'AudioOut[1]' whether declared by in the platform descriptor file or the user, start with an upper case letter. Identifiers are constructed using letters, digits, and underscores. Identifiers are case sensitive. A single upper case letter is the shortest possible identifier. .. index:: single: comment .. index:: single: # **Comments** in Stride are preceded by the number sign ``#``. Let's now stream the input to two outputs creating a mono to stereo connection. :: # Stream audio input 1 to audio output 1 AudioIn[1] >> AudioOut[1]; # Stream audio input 1 to audio output 2 AudioIn[1] >> AudioOut[2]; In this example the `hybrid stream` output port of ``AudioIn[1]`` is connected and streams to multiple `hybrid stream` input ports. The `hybrid stream` input ports are those of ``AudioOut[1]`` and ``AudioOut[2]``. The same program can be written as follows:: # Stream audio input 1 to audio output 1 and audio output 2 AudioIn[1] >> [AudioOut[1], AudioOut[2]]; "``[AudioOut[1], AudioOut[2]]``" represents a **block bundle** in Stride. Elements of a bundle block are placed between square brackets and separated by commas. Elements of a bundle must have the same block type. Let's now stream two inputs to two outputs creating a stereo to stereo connection. :: # Stream audio input 1 and 2 to audio output 1 and 2 (one to one) [AudioIn[1], AudioIn[2]] >> [AudioOut[1], AudioOut[2]]; This is equivalent to writing:: # Stream audio input 1 to audio output 1 AudioIn[1] >> AudioOut[1]; # Stream audio input 2 to audio output 2 AudioIn[2] >> AudioOut[2]; :: # Stream audio input 1 and 2 to audio output 1 and 2 (one to one) using range indexing AudioIn[1:2] >> AudioOut[1:2]; The identifiers used so far are all defined in the platform descriptor file. What if we would like to label these identifiers to give them names that make sense in a project context like a stereo guitar effects pedal? This could be achieved by defining new :ref:`signal blocks `. .. _exampleStream: :: # Declare a signal block labeled 'Microphone' signal Microphone { default: 0.0 rate: AudioRate reset: MasterReset meta: 'Microphone input.' } # Declare a signal block bundle labeled 'MainOutput' signal MainOutput [2] { default: 0.0 rate: AudioRate reset: MasterReset meta: 'Main stereo output.' } # Stream 'AudioIn[1]' to 'Microphone' AudioIn[1] >> Microphone; # Stream 'MainOutput' to 'AudioOut[1]' and 'AudioOut[2]' MainOutput >> AudioOut[1:2]; # Stream 'Microphone' to 'MainOutput' Microphone >> MainOutput; The first expression in the preceding code is a signal block declaration. It begins with the ``signal`` keyword followed by an identifier chosen by the user, in this case 'Microphone'. Braces enclose the **properties** of a signal block and their corresponding assignments. Like identifiers, properties in Stride expose ports to enable connections with a block. However, unlike identifiers, connections through properties can only be made during declarations. Some properties expose a single port and others expose multiple ports. A property exposing multiple ports is a **multi-port property**. A multi-port property exposes ports that have the same direction. Stride establishes the proper connection by matching the port type. If a port is to be left unconnected during declaration, its corresponding property is assigned the keyword ``none``. A signal block has four properties which expose all of its four ports: **TABLE GOES HERE** The ``input`` and ``output`` properties expose the `hybrid stream` input and output ports respectively. In the case of ``Microphone``, its connection with ``AudioIn[1]`` is established through the ``input`` property "``input: AudioIn[1]``" but with ``MainOutput`` it is established using its identifier and the stream operator "``Microphone >> MainOutput``". Here's how the connection between ``Microphone`` and ``AudioIn[1]`` could have been established using its identifier and the stream operator:: # Declare a signal block labeled 'Microphone' signal Microphone { default: 0.0 rate: AudioRate reset: MasterReset meta: 'Microphone input' } # Stream audio input 1 to 'Microphone' AudioIn[1] >> Microphone; The ``rate`` property, as its name indicates, sets the sampling rate of the signal block. It can accept a connection from a :ref:`constant block ` which has an output port of type `constant integer`. :ref:`AudioRate` is a platform defined constant block. It holds the value of the hardware audio sampling rate. The ``meta`` property holds metadata information related to the block. It can accept a connection from a constant block which has an output port of type `constant string`. :: # Stream 'AudioIn[1]' to 'Microphone' AudioIn[1] >> Microphone; # Stream 'MainOutput' to 'AudioOut[1]' and 'AudioOut[2]' MainOutput >> AudioOut[1:2]; # Stream 'Microphone' to 'MainOutput' Microphone >> MainOutput; Stride will automatically generate the following prefix code:: signal Microphone {} signal MainOutput [2] {} Automatic code generation is possible with signal blocks. When a declaration is made with empty braces, the default values are assigned to the properties. :: signal Microphone { default: 0.0 rate: AudioRate domain: AudioDomain reset: MasterReset meta: none } signal MainOutput [2] { default: 0.0 rate: AudioRate domain: AudioDomain reset: MasterReset meta: none } Stride ignores **whitespace** characters (**space**, **tab**, **newline**) . It also ignores **semicolons** at the end of property assignments, block declarations. The following code samples are equivalent:: # Sample 1 signal Microphone { default: 0.0 rate: AudioRate reset: MasterReset meta: 'Microphone input.' } # Sample 2 signal Microphone {default: 0.0 rate: AudioRate reset: MasterReset meta: 'Microphone input.'} # Sample 3 signal Microphone { default: 0.0; rate: AudioRate; reset: MasterReset; meta: 'Microphone input.'; }; # Sample 4 signal Microphone { default: 0.0; rate: AudioRate; reset: MasterReset; meta: 'Microphone input.'; };