ProTracker is a popular music tracker to sequence music on a Commodore Amiga machine. As I still own a Commodore Amiga 500, I thought it would be a nice challenge to develop an R package that could handle ProTracker module files, and so I did. The first version of this package was just released on CRAN.
In this post I will briefly explain what ProTracker modules are and how they work. Then I will give a short demonstrations of the current sweetness the ProTrackR package has to offer. On this blog I will try to keep you updated on new versions of this package and its new features.
The module (MOD) is a computer file format used primarily to represent music. A MOD file contains a set of instruments in the form of samples, a number of patterns indicating how (which notes and effects) and when the samples are to be played, and a list of what patterns to play in what order.
The first release of the ProTrackR package contains the bare bones required to import and export such module files, and modify them any way you'd like (and the file format restrictions allow you to). This is a good time to start with an example. Let's start by loading the module 'Elekfunk' from The Mod Archive.
# required packages: | |
require(plot3D) | |
require(ProTrackR) | |
# Read the module 'elekfunk' from the Mod Archive: | |
con <- url("http://api.modarchive.org/downloads.php?moduleid=41528", "rb") | |
mod <- read.module(con) | |
close(con) | |
rm(con) | |
# see how much memory the module object is eating: | |
format(object.size(mod), "Kb") | |
# calculate the ratio between the size of the object | |
# in memory and the size of the mod.file: | |
print(as.numeric(object.size(mod)/moduleSize(mod))) | |
# note that the object is roughly four times the size as the original file. | |
# This is probably because the Wave object (which the ProTrackerSample objec | |
# enherits), stores 8 bit wave data as integer values. In R, integers are | |
# actually 32-bit long, which explains the factor (32 / 8 =) 4 difference. |
This module was used in a demo by Sanity to show off the Amiga's capabilities, which were impressive ate the time.
Playing routines in the ProTrackR package are currently limited to just playing the samples at specific notes (more fancy routines are in development). The examples below show how to play all samples in a module, a specific sample at different notes and applying different fine tunes. But at least you can export them as wave files.
# play all samples in the module at note "C-3" | |
playSample(mod) | |
# play chromatic scales of octaves 2 and 3 using the 23rd sample | |
data(period_table) | |
for (i_note in as.vector(outer(names(period_table)[-1:-2], | |
c(2:3), function(x, y) paste(x, y, sep = "")))) | |
{ | |
print(i_note) | |
playSample(PTSample(mod, 23), 0.1, T, i_note, 0.5) | |
} | |
# play all finetunes of C-3 | |
for (ft in -8:7) | |
{ | |
print(ft) | |
playSample(PTSample(mod, 23), 0.1, T, "C-3", 0.5, finetune = ft) | |
} | |
# export one of the samples as *.wav file | |
writeWave(PTSample(mod, 25), "guitar slide.wav") |
Combined with the power of R, all kinds of fancy analyses become possible. The module for instance contains a sample of a guitar slide. In R we can now generate a power spectrum (which would have been tricky to do real time on an original chipset Amiga).
# select a sample: | |
plot_samp <- PTSample(mod, 25) | |
# generate power spectrum | |
spec <- powspec(waveform(plot_samp), | |
wintime = 0.1, | |
steptime = 0.005) | |
spec_cutoff <- quantile(log10(spec), 0.01) | |
spec[log10(spec) < spec_cutoff] <- 10^spec_cutoff | |
# fancy 3D plot of waveform and powerspectrum | |
png("powerspec.png", 600, 300, type = "cairo", | |
bg = "transparent", pointsize = 14) | |
par(oma = c(0,0,0,0), mar = c(0.5,0.5,0.5,0.5)) | |
lines3D(x = 60*(0:(length(plot_samp) - 1))/(length(plot_samp) - 1), | |
y = rep(15, length(plot_samp)), | |
z = 3 + 11*waveform(plot_samp)/255, | |
phi = 40, theta = 21, lwd = 0.15, | |
xlim = c(0,60), ylim = c(0,15), zlim = c(-3, 14.5), | |
xlab = "time", ylab = "Frequency", zlab = "Amplitude", | |
col = "black", lwd = 0.5, scale = F, bty = "b2") | |
persp3D(x = 60*((1:ncol(spec)) - 1)/(ncol(spec) - 1), | |
y = 15*((1:(nrow(spec) - 3)) - 1)/(nrow(spec) - 4), | |
z = t(log10(spec))[,-(1:3)], | |
xlab = "time", ylab = "Frequency", zlab = "Amplitude", | |
add = T, colkey = F, shade = 0.1) | |
dev.off() |
The power spectrum shows the shift in frequency which you would expect for a guitar slide. There are plenty other examples I could show you here but leave it at this for the moment. Hopefully you enjoyed these examples of the ProTrackR package, please stay tuned for updates on this package.