---
title: "Selecting and assinging ProTrackR2 objects"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Selecting and assinging ProTrackR2 objects}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
## Introduction
This vignette describes how to select elements from ProTrackR2 module objects and
how to replace them. In order to best understand this, it is necessary to understand
how objects are organised in the ProTrackR2 package. Please read `vignette("s3class")`
first, or use it for reference when reading the vignette at hand. Before we continue,
we start the session by loading a module file.
```{r setup}
library(ProTrackR2)
mod <- pt2_read_mod(system.file("mod.intro", package = "ProTrackR2"))
```
## Selecting lists from modules
There are two important lists of objects contained in ProTracker modules.
The first is a list of patterns (`pt2patlist`), which can be obtained as follows.
```{r get-patlist}
mod$patterns
## which is identical to
mod[["patterns"]]
## which is identical to
mod[[1L]]
```
It returns a list of patterns and inherits the class `pt2patlist`, from it you
can select one ore more specific patterns (see below).
The second list you can get from a module is a list of samples (`pt2samplist`),
which can be obtained as follows.
```{r get-samplist}
mod$samples
## which is identical to
mod[["samples"]]
## which is identical to
mod[[2L]]
```
## Index base: one or zero?
For vectors and lists, `R` uses indices starting at 1. ProTracker modules often use arrays
of elements that starting with indices at 0 (but unfortunately consistently for everything).
And in some case ProTracker effect commands refer to such indices. Unfortunately, this is
a source of confusion, for which there exists no ideal solution.
In this package, I've tried to implement it as consistent as possible. Named functions and
methods use zero-based indices, whereas bracket operators (`[` and `[[`) use one-based
indices conform `R` syntax. This is summarised in the table below.
Zero-based index |
One-based index |
`pt2_cell()`, `pt2_pattern()`, `pt2_sample()` |
`[`, `[[` |
## Selecting and replacing list elements
### Samples
Selecting a specific sample from a sample list can be done with the `[[`-operator. Note
that sample number 5 is empty (consists of zero samples):
```{r sample-sel}
mod$samples[[5L]]
## which is identical to (see the different base of the index)
pt2_sample(mod, 4L)
```
In order to replace this sample with sample number 2, you can simply assign it like this:
```{r sample-assign}
mod$samples[[5L]] <- mod$samples[[2L]]
```
After this assignment operation samples 2 and 5 are identical. If you want to replace multiple
samples at once you need to use the `[`-operator. The example below shows how to replace samples
5 up to 8 with sample 2:
```{r samples-assign}
mod$samples[5L:8L] <- mod$samples[2L]
```
Single brackets `[` returns a list (`pt2samplist`) with one or more elements. Double
brackets `[[` return a single element (`pt2samp`). In essence, this works the same as
with normal `list` objects.
### Patterns
For a pattern lists (`pt2patlist`) selection and assignment operators are similar to those of sample
lists (see above). Single brackets `[` returns a list (`pt2patlist`) with one or more elements. Double
brackets `[[` return a single element (`pt2pat`). In essence, this works the same as
with normal `list` objects.
The range of pattern indices you can use depends on the maximum index (+1) registered in the
pattern sequence table (`pt2_pattern_table(mod)`). In the currently loaded module there are
4 patterns registered. So to get the fourth pattern table in the module, you use:
```{r pat-sel}
my_pattern <- mod$patterns[[4L]]
## which is identical to (see the different base of the index)
my_pattern <- pt2_pattern(mod, 3L)
```
If you attempt to get the fifth table (`mod$patterns[[5]]`), you will get an error, since it doesn't exist.
However, you can append a new pattern table at this position using the assign operator:
```{r pat-assign}
mod$patterns[[5L]] <- pt2_new_pattern()
```
This new pattern is also automatically added to the pattern sequence table:
```{r pat-seq}
pt2_pattern_table(mod)
```
You can use the same strategy to copy existing patterns to a new index:
```{r pat-copy}
mod$patterns[[6L]] <- mod$patterns[[1L]]
```
In theory ProTracker modules can hold a maximum of 100 pattern tables. If this limit can be reached
depends on available slots in the pattern sequence table (`pt2_pattern_table(mod)`). If you
try to create a pattern beyond the maximum of 100 or there are no more room for additional patterns
in the sequence table, you will get an error.
### Cells
As explained in `vignette("s3class")`, a cell (class `pt2cell`) is the elementary unit of a pattern
table and specifies which instrument (sample) to play at which note and with which effect.
You can select a range of cells with a `[`-operator by referring to a pattern's row index and
its channel (column) index. The example below selects the first 8 rows from the first channel.
```{r cells-select}
my_cells <- mod$patterns[[1L]][1L:8L, 1L]
```
The result of this is an object of class `pt2celllist`. To select a particular cell from this range
you need the double bracket operator `[[`. To select the first cell of the eight selected cells you
do the following.
```{r cell-select}
my_cells[[1L]]
## which is identical to (see the different base of the indices)
pt2_cell(pt2_pattern(mod, 0L), i = 0L, j = 0L)
```
Remember that we appended an empty pattern at position 5? We can replace the empty cells in that
pattern with the selected cells. The example below shows how the entire first column is filled
with the 8 selected cells (note that the cells are recycled).
```{r cell-copy}
mod$patterns[[5L]][,1L] <- my_cells
```