From 94f675e058ae13fce320e1d53a87d8e3442076da Mon Sep 17 00:00:00 2001 From: pepijn-devries Date: Sun, 12 Jan 2025 01:22:36 +0100 Subject: [PATCH 1/2] Deprecated ModArchive and ModLand functions; updated documentation --- .github/workflows/R-CMD-check.yaml | 51 ++ DESCRIPTION | 5 +- NEWS.md | 94 +-- R/01supporting_functions.r | 4 +- R/02PTCell.r | 12 +- R/03PTTrack.r | 14 +- R/04PTPattern.r | 14 +- R/05PTSample.r | 97 ++- R/06PTModule.r | 84 ++- R/07PTBlock.r | 8 +- R/08coercion.r | 6 +- R/09playing_routines.r | 147 ++--- R/{11MODPlugHelpers.r => 10MODPlugHelpers.r} | 32 +- R/10ModArchiveHelpers.r | 657 ------------------- R/12ModLandHelpers.r | 129 ---- R/deprecated.R | 90 +++ README.Rmd | 7 + README.md | 9 + man/MODPlugToPTPattern.Rd | 4 +- man/PTPatternToMODPlug.Rd | 8 +- man/deprecated.Rd | 51 ++ man/fix.PTModule.Rd | 6 +- man/modArchive.Rd | 314 --------- man/modLand.Rd | 96 --- man/modToWave.Rd | 2 - man/playMod.Rd | 10 +- man/playSample.Rd | 33 +- man/playWave.Rd | 18 +- man/playingtable.Rd | 6 +- man/plot.Rd | 2 +- man/rawToPTModule.Rd | 4 +- man/read.module.Rd | 19 +- man/read.sample.Rd | 7 +- man/write.module.Rd | 7 +- man/write.sample.Rd | 9 +- 35 files changed, 480 insertions(+), 1576 deletions(-) create mode 100644 .github/workflows/R-CMD-check.yaml rename R/{11MODPlugHelpers.r => 10MODPlugHelpers.r} (93%) delete mode 100644 R/10ModArchiveHelpers.r delete mode 100644 R/12ModLandHelpers.r create mode 100644 R/deprecated.R create mode 100644 man/deprecated.Rd delete mode 100644 man/modArchive.Rd delete mode 100644 man/modLand.Rd diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml new file mode 100644 index 0000000..562fe0f --- /dev/null +++ b/.github/workflows/R-CMD-check.yaml @@ -0,0 +1,51 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + +name: R-CMD-check.yaml + +permissions: read-all + +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - {os: macos-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 + with: + upload-snapshots: true + build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' diff --git a/DESCRIPTION b/DESCRIPTION index 7b3463e..83338b5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,7 @@ Package: ProTrackR Type: Package Title: Manipulate and Play 'ProTracker' Modules -Version: 0.4.3 -Date: 2024-02-15 +Version: 0.4.3.0001 Authors@R: c(person("Pepijn", "de Vries", role = c("aut", "cre", "dtc"), email = "pepijn.devries@outlook.com", comment = c(ORCID = "0000-0002-7961-6646"))) @@ -20,7 +19,7 @@ Description: 'ProTracker' is a popular music tracker to sequence License: GPL (>= 3) LazyData: True Depends: audio, lattice, signal, tuneR (>= 1.0) -Imports: graphics, methods, stats, utils, XML +Imports: graphics, methods, stats, utils Suggests: AmigaFFH (>= 0.2.0) Encoding: UTF-8 RoxygenNote: 7.2.3 diff --git a/NEWS.md b/NEWS.md index 79451ff..f8f4ed6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,130 +1,110 @@ -ProTrackR v0.4.3 (Release date: 2023-02-15) +ProTrackR v0.4.3.0001 +============= + + * Fixed CRAN note + * Updated documentation + * Migrated ModArchive and modLand functions to the `openmpt` package + +ProTrackR v0.4.3 ============= * Added `pkgdown` website and README * switched to RMarkdown mode for roxygen2 documentation -ProTrackR v0.3.8 (Release date: 2023-08-22) +ProTrackR v0.3.8 ============= * Updates to comply with latest CRAN policies and Roxygen2 standards -ProTrackR v0.3.7 (Release date: 2020-02-03) +ProTrackR v0.3.7 ============= * Fixes to modArchive functions, due to changes to their API - * Fix in structure and examples to pass CRAN tests. - * Fix in validation functions in order to support changes in latest version of R -ProTrackR v0.3.6 (Release date: 2019-02-06) +ProTrackR v0.3.6 ============= * Added modLand helper functions. - * Reading and writing 8svx samples with read.sample and write.sample is now implemented using the AmigaFFH package, which has a more robust implementation of Interchange File Format handlers. - * Added a 'mix' argument to the 'modToWave'-method. When set to FALSE, the method can now return all individual channels (without mixing them). - * The 'playWave'-method was updated such that it also accepts multi-channel waves (WaveMC), in order to make it compatible with the modification specified above. - * Available documentation on which of the 4 channels are mixed to the left and right audio output channel respectively is inconsistent. This version will assume that channels 1 and 4 (or 0 and 3 using Amiga indexing) are mixed to the left channel and channels 2 and 3 (or 1 and 2 using Amiga indexing) are mixed to the right channel. This means that the output channels are now swapped compared to earlier versions of this package. - * There was a bug in the implementation of the 'porta to note' effects (3 and 5), it is now fixed. - * Added a new implementation of the generic 'as.raw' method, which allows to convert PTModule objects into raw data. Also added a 'rawToPTModule' method to achieve the inverse. - * Endianess should have been set to "big" instead of "little" (whoops), luckily, this has no consequences as all data are read as raw data. I have corrected the code nonetheless - * Minor corrections to manual -ProTrackR v0.3.5 (Release date: 2017-10-14) +ProTrackR v0.3.5 ============= * Added functions to exchange pattern data with MODPlug tracker. - * Endianness is explicitely set to "little" when reading and writing samples and modules. As all data is read and written as raw, this should not affect the package functioning. - * Removed unnecessary print statement from PTBlock routine. - * Fixed a bug in the 'rawToCharNull' function. - * Fixed a bug in the 'modToWave' routine that caused an error under rare conditions. - * Setting stereo.separation to 0 was not handled correctly in 'modToWave' routine. Channels were not mixed before converting to mono. This is now fixed. -ProTrackR v0.3.4 (Release date: 2016-11-25) +ProTrackR v0.3.4 ============= * added a "fix.PTModule" method that attempts to fix a module object when it is not conform ProTracker specs... - * period limits for the porta effects have been fixed - * inverted the logical interpretation of the 'verbose' argument, as it was incorrect in earlier versions. - * added and modified several of the 'modArchive'- functions, for better support from modarchive.org - * modified S4-object validation functions such that they run faster. - * modified 'write.module'-method such that it will write modules much faster - * fixed bug in 'read.module'-method and modified it such that it will read modules much faster. - * fixed bug in 'loopStart<-'-method - * fixed bug in 'loopLength<-'-method - * fixed bug in 'patternOrder<-'-method - * fixed bug in 'appendPattern'-method - * fixed bug in 'volume<-'-method - * fixed bug in 'waveform<-'- and 'waveform'-method -ProTrackR v0.3.3 (Release date: 2016-03-26) +ProTrackR v0.3.3 ============= * Minor correction in manual. -ProTrackR v0.3.2 (Release date: 2016-03-25) +ProTrackR v0.3.2 ============= * Minor corrections in manual. -ProTrackR v0.3.1 (Release date: 2016-03-25) +ProTrackR v0.3.1 ============= * Modified the playing routine such that the porta @@ -135,127 +115,97 @@ ProTrackR v0.3.1 (Release date: 2016-03-25) Protracker v2.3D clone for modern machines, https://16-bits.org/pt.php) for confirming these software and hardware limits. - * Resampling routine in the modToWave-method is rewritten. It should be faster now. - * The 9xy command is now implemented such that it emulates the ProTracker 'offset bug'. Therewith, the player routine now passes 'ptoffset.mod' test. - * Bug in resampling of samples in 'modToWave'- routine is fixed. - * 'modArchive' functions are added to the package. - * Effect commands 'E4x' and 'E7x' are now implemented in the player routine. - * Implementation of effect command '5xy' is fixed. - * In the previous release, some generated wave data ended up out of range in the mixing procedure. This is now fixed. - * The 'playWave'-method is modified such that it returns an 'audioInstance'-object (audio package) allowing control over the playback. - * Minor corrections/improvements to the manual - * Mixing when some tracks are turned off is fixed -ProTrackR v0.2.3 (Release date: 2015-11-07) +ProTrackR v0.2.3 ============= * Minor corrections in manual to pass CRAN checks. -ProTrackR v0.2.2 (Release date: 2015-11-07) +ProTrackR v0.2.2 ============= * Minor corrections in manual to pass CRAN checks. -ProTrackR v0.2.1 (Release date: 2015-11-07) +ProTrackR v0.2.1 ============= * 'clearSamples'-method was added to the package. - * 'clearSong'-method was added to the package. - * 'modToWave'-method was added to the package - * 'playingtable'-method was added to the package - * 'playMod'-method was added to the package - * 'playWave'-method was added to the package - * 'resample'-function added to the package to avoid 'seewave' dependency (which is not available for all platforms). - * 'waveform'-method now includes additional arguments: 'start.pos', 'stop.pos' and 'loop' - * removed 'utils' import... - * 'name' method, for PTSample objects, incorrectly returned raw representation of the sample name instead of a character representation. This is now fixed. - * 'playSample' was printing the names of additional (...) arguments in previous release. This was meant as a test and this behaviour was not intended for the release. It has been removed. - * A section on ProTracker effect commands is added to the manual - * Some minor corrections were made in the manual -ProTrackR v0.1.3 (Release date: 2015-09-25) +ProTrackR v0.1.3 ============= * Some more minor fixes to pass CRAN checks. - -ProTrackR v0.1.2 (Release date: 2015-09-25) +ProTrackR v0.1.2 ============= * Minor fixes to pass CRAN checks. - * In the 'playSample' method, the 'finetune' argument is now correctly passed to the 'noteToSampleRate' function. Before, it was only possible to play at the finetune specified for a sample. - * Correction in the validity check for objects of S4 class 'PTSample': wlooplen is allowed to have a value of zero when the sample is empty. - * The prototype of the S4 class 'PTSample' is changed to set the wlooplen value to zero. - * The slot descriptions for wloopstart and wlooplen in the 'PTSample' documentation contained errors that were corrected. - * The 'loopLength<-', the 'PTSample-method' and 'read.sample' methods were modified to handle the adjustments to the 'PTSample' class. - * Removed superfluous argument 'value' from the 'patternLength' method -ProTrackR v0.1.1 (Release date: 2015-09-25) +ProTrackR v0.1.1 ============= First release: * Provided the basis for importing, exporting and manipulating ProTracker modules. - * Basic playing routine, playing the samples in the module only (not the module itself). diff --git a/R/01supporting_functions.r b/R/01supporting_functions.r index d1354af..4a723b4 100644 --- a/R/01supporting_functions.r +++ b/R/01supporting_functions.r @@ -27,7 +27,7 @@ #' @export rawToCharNull <- function(raw_dat) { result <- "" - if (length(raw_dat) < 3) try(result <- (rawToChar(raw_dat)), silent = T) else + if (length(raw_dat) < 3) try(result <- (rawToChar(raw_dat)), silent = TRUE) else { result <- raw_dat runlength <- rle(result)$lengths @@ -39,7 +39,7 @@ rawToCharNull <- function(raw_dat) { result[rel_range][result[rel_range] == as.raw(0x00)] <- as.raw(0x20) result <- result[result != raw(1)] } - try(result <- rawToChar(result), silent = T) + try(result <- rawToChar(result), silent = TRUE) if ("raw" %in% class(result)) result <- "" } return(result) diff --git a/R/02PTCell.r b/R/02PTCell.r index ea2ce03..bd51b46 100644 --- a/R/02PTCell.r +++ b/R/02PTCell.r @@ -1,23 +1,23 @@ validity.PTCell <- function(object) { - if (length(object@data) != 4) return (F) + if (length(object@data) != 4) return (FALSE) # Data in vector should be of type raw - if (typeof(object@data) != "raw") return (F) + if (typeof(object@data) != "raw") return (FALSE) # max. 32 samples (including number 0) allowed: - if (sampleNumber(object) > 0x1F) return (F) + if (sampleNumber(object) > 0x1F) return (FALSE) period.value = .periodFromCell(object) if (period.value != 0) { # only octave 1 up to 3 allowed - if (!(octave(period.value) %in% as.character(1:3))) return (F) + if (!(octave(period.value) %in% as.character(1:3))) return (FALSE) # period value should be in ProTracker period table if (!(period.value %in% unlist(ProTrackR::period_table[ProTrackR::period_table$tuning == 0, - !(names(ProTrackR::period_table) %in% c("octave", "tuning"))]))) return (F) + !(names(ProTrackR::period_table) %in% c("octave", "tuning"))]))) return (FALSE) } - return (T) + return (TRUE) } #' The PTCell class diff --git a/R/03PTTrack.r b/R/03PTTrack.r index a1a13b0..3f9e7fc 100644 --- a/R/03PTTrack.r +++ b/R/03PTTrack.r @@ -1,27 +1,27 @@ validity.PTTrack <- function(object) { # Data should consist of a raw maximumPatternTableRowCount x 4 matrix - if (!all(dim(object@data) == c(maximumPatternTableRowCount, 4))) return (F) + if (!all(dim(object@data) == c(maximumPatternTableRowCount, 4))) return (FALSE) # Data in matrix should be of type raw - if (typeof(object@data) != "raw") return (F) + if (typeof(object@data) != "raw") return (FALSE) # All cell data should also be OK # max. 32 samples (including number 0) allowed: samp.num <- hiNybble(object@data[,1])*0x01 + hiNybble(object@data[,3]) - if (any(samp.num > 0x1F)) return (F) + if (any(samp.num > 0x1F)) return (FALSE) per <- loNybble(object@data[,1])*0x100 + as.integer(object@data[,2]) oct <- octave(per) # only octaves 1 up to 3 are allowed: - if (any(!(oct[per != 0] %in% c(1:3)))) return (F) + if (any(!(oct[per != 0] %in% c(1:3)))) return (FALSE) # only period values from period_table are allowed: if (any(!(per[per != 0] %in% unlist(ProTrackR::period_table[ProTrackR::period_table$tuning == 0, !(names(ProTrackR::period_table) %in% c("octave", "tuning"))])))) - return (F) + return (FALSE) - return(T) + return(TRUE) } #' The PTTrack class @@ -80,7 +80,7 @@ setClass("PTTrack", representation(data = "matrix"), prototype(data = matrix(rep(as.raw(new("PTCell")), maximumPatternTableRowCount), - nrow = maximumPatternTableRowCount, byrow = T)), + nrow = maximumPatternTableRowCount, byrow = TRUE)), validity = validity.PTTrack) #' @rdname as.character diff --git a/R/04PTPattern.r b/R/04PTPattern.r index 83f3009..9588775 100644 --- a/R/04PTPattern.r +++ b/R/04PTPattern.r @@ -1,29 +1,29 @@ validity.PTPattern <- function(object) { # Data should consist of a raw maximumPatternTableRowCount x maximumTrackCount*4 matrix - if (!all(dim(object@data) == c(maximumPatternTableRowCount, maximumTrackCount*4))) return (F) + if (!all(dim(object@data) == c(maximumPatternTableRowCount, maximumTrackCount*4))) return (FALSE) # data should be of type raw - if (typeof(object@data) != "raw") return (F) + if (typeof(object@data) != "raw") return (FALSE) # tracks should also be OK trackdat <- do.call(rbind, lapply(as.list(1:maximumTrackCount), function (x) { object@data[,-3 + ((x*4):(x*4 + 3))] })) # max. 32 samples (including number 0) allowed: samp.num <- hiNybble(trackdat[,1])*0x01 + hiNybble(trackdat[,3]) - if (any(samp.num > 0x1F)) return (F) + if (any(samp.num > 0x1F)) return (FALSE) per <- loNybble(trackdat[,1])*0x100 + as.integer(trackdat[,2]) oct <- octave(per) # only octaves 1 up to 3 are allowed: - if (any(!(oct[per != 0] %in% c(1:3)))) return (F) + if (any(!(oct[per != 0] %in% c(1:3)))) return (FALSE) # only period values from period_table are allowed: if (any(!(per[per != 0] %in% unlist(ProTrackR::period_table[ProTrackR::period_table$tuning == 0, !(names(ProTrackR::period_table) %in% c("octave", "tuning"))])))) - return (F) + return (FALSE) - return(T) + return(TRUE) } #' The PTPattern class @@ -72,7 +72,7 @@ setClass("PTPattern", representation(data = "matrix"), prototype(data = matrix(raw(maximumPatternTableRowCount*maximumTrackCount*4), ncol = maximumTrackCount*4, - nrow = maximumPatternTableRowCount, byrow = T)), + nrow = maximumPatternTableRowCount, byrow = TRUE)), validity = validity.PTPattern) #' @rdname as.character diff --git a/R/05PTSample.r b/R/05PTSample.r index d37617d..6481062 100644 --- a/R/05PTSample.r +++ b/R/05PTSample.r @@ -1,26 +1,26 @@ validity.PTSample <- function(object) { - if (length(object@name) != 22) return(F) - if (length(object@finetune) != 1) return(F) - if (length(object@volume) != 1) return(F) - if (length(object@wloopstart) != 2) return(F) - if (length(object@wlooplen) != 2) return(F) - if (2*rawToUnsignedInt(object@wloopstart) > length(object@left)) return(F) + if (length(object@name) != 22) return(FALSE) + if (length(object@finetune) != 1) return(FALSE) + if (length(object@volume) != 1) return(FALSE) + if (length(object@wloopstart) != 2) return(FALSE) + if (length(object@wlooplen) != 2) return(FALSE) + if (2*rawToUnsignedInt(object@wloopstart) > length(object@left)) return(FALSE) if ((2*(rawToUnsignedInt(object@wlooplen) + rawToUnsignedInt(object@wloopstart)) > length(object@left)) && - rawToUnsignedInt(object@wlooplen) != 1) return(F) + rawToUnsignedInt(object@wlooplen) != 1) return(FALSE) # loop length can only be zero when the sample is empty if (rawToUnsignedInt(object@wlooplen) == 0 && - length(object@left) > 0) return(F) - if (object@bit != 8) return(F) - if (!object@pcm) return(F) - if (as.integer(object@volume) > 0x40) return(F) - if (as.integer(object@finetune) > 0x0F) return(F) - if (length(object@right) > 0) return(F) - if (length(object@left) > 2*0xFFFF) return(F) + length(object@left) > 0) return(FALSE) + if (object@bit != 8) return(FALSE) + if (!object@pcm) return(FALSE) + if (as.integer(object@volume) > 0x40) return(FALSE) + if (as.integer(object@finetune) > 0x0F) return(FALSE) + if (length(object@right) > 0) return(FALSE) + if (length(object@left) > 2*0xFFFF) return(FALSE) # sample length should be even! - if ((length(object@left)%%2) == 1) return(F) - return (T) + if ((length(object@left)%%2) == 1) return(FALSE) + return (TRUE) } #' The PTSample class @@ -123,7 +123,7 @@ setClass("PTSample", wlooplen = raw(2), samp.rate = 16574.28, #can't seem to be able to call a function (noteToSampleRate) from the constructor bit = 8, - stereo = F), + stereo = FALSE), contains = "Wave", validity = validity.PTSample) @@ -333,7 +333,7 @@ setMethod("loopStart", "PTSample", function(sample){ #' @export setReplaceMethod("loopStart", c("PTSample", "ANY"), function(sample, value){ value <- value[[1]] - if (is.na(value) || value == "off" || (is.logical(value) && value == F)) + if (is.na(value) || value == "off" || (is.logical(value) && value == FALSE)) { sample@wloopstart <- unsignedIntToRaw(0, 2) sample@wlooplen <- unsignedIntToRaw(1, 2) @@ -409,7 +409,7 @@ setMethod("loopLength", "PTSample", function(sample){ setReplaceMethod("loopLength", c("PTSample", "ANY"), function(sample, value){ value <- value[[1]] value <- as.integer(round(value/2)) - if (is.na(value) || value == "off" || value == F) + if (is.na(value) || value == "off" || value == FALSE) { sample@wloopstart <- unsignedIntToRaw(0, 2) sample@wlooplen <- unsignedIntToRaw(1, 2) @@ -446,7 +446,7 @@ setMethod("print", "PTSample", function(x, ...){ cat(paste("\tFinetune:", fineTune(x), "\n", sep = "\t\t\t")) }) -setGeneric("playSample", function(x, silence = 0, wait = T, +setGeneric("playSample", function(x, silence = 0, wait = TRUE, note = "C-3", loop = 1, ...){ standardGeneric("playSample") }) @@ -494,25 +494,24 @@ setGeneric("playSample", function(x, silence = 0, wait = T, #' Can be used to change the video mode, or finetune argument for the call to that method. #' @returns Returns nothing but plays the sample(s) as audio. #' @examples -#' \dontrun{ -#' data("mod.intro") -#' -#' ## play all samples in mod.intro: -#' playSample(mod.intro, 0.2, loop = 0.5) -#' -#' ## play a chromatic scale using sample number 3: -#' for (note in c("A-2", "A#2", "B-2", "C-3", "C#3", -#' "D-3", "D#3", "E-3", "F-3", "F#3", -#' "G-3", "G#3")) -#' { -#' playSample(PTSample(mod.intro, 3), note = note, silence = 0.05, loop = 0.4) -#' } -#' -#' ## play the sample at a rate based on a specific -#' ## video mode and finetune: -#' playSample(PTSample(mod.intro, 3), video = "NTSC", finetune = -5) +#' if (interactive()) { +#' data("mod.intro") +#' +#' ## play all samples in mod.intro: +#' playSample(mod.intro, 0.2, loop = 0.5) +#' +#' ## play a chromatic scale using sample number 3: +#' for (note in c("A-2", "A#2", "B-2", "C-3", "C#3", +#' "D-3", "D#3", "E-3", "F-3", "F#3", +#' "G-3", "G#3")) +#' { +#' playSample(PTSample(mod.intro, 3), note = note, silence = 0.05, loop = 0.4) +#' } +#' +#' ## play the sample at a rate based on a specific +#' ## video mode and finetune: +#' playSample(PTSample(mod.intro, 3), video = "NTSC", finetune = -5) #' } -#' #' @author Pepijn de Vries #' @family sample.operations #' @family sample.rate.operations @@ -543,7 +542,7 @@ setMethod("playSample", "PTSample", function(x, silence, wait, note, loop, ...){ x@samp.rate <- sr if(silence > 0) x <- tuneR::bind(x, silence(silence, samp.rate = sr, - bit = 8, pcm = T, xunit = "time")) + bit = 8, pcm = TRUE, xunit = "time")) if (wait) { audio::wait(audio::play(vl*(x@left - 128)/128, @@ -585,16 +584,15 @@ setGeneric("read.sample", function(filename, what = c("wav", "mp3", "8svx", "raw #' installed in order to read 8svx files. #' @returns Returns a `PTSample` object based on the file read. #' @examples -#' \dontrun{ #' data("mod.intro") #' +#' f <- tempfile(fileext = ".iff") #' ## create an audio file which we can then read: -#' write.sample(PTSample(mod.intro, 2), "snaredrum.iff", "8svx") +#' write.sample(PTSample(mod.intro, 2), f, "8svx") #' #' ## read the created sample: -#' snare <- read.sample("snaredrum.iff", "8svx") +#' snare <- read.sample(f, "8svx") #' print(snare) -#' } #' #' @note As per ProTracker standards, a sample should have an even length #' (in bytes). If a sample file has an odd length, a `raw` `0x00` value @@ -646,7 +644,7 @@ setMethod("read.sample", c("character", "ANY"), function(filename, what = c("wav if (!("AmigaFFH" %in% utils::installed.packages())) stop("You need to install package 'AmigaFFH' in order to load 8svx files.") result <- AmigaFFH::read.iff(filename) samp.name <- raw(22) - try(samp.name <- AmigaFFH::getIFFChunk(result, c("8SVX", "NAME"))@chunk.data[[1]], silent = T) + try(samp.name <- AmigaFFH::getIFFChunk(result, c("8SVX", "NAME"))@chunk.data[[1]], silent = TRUE) samp.name <- samp.name[1:22] samp.name[is.na(samp.name)] <- raw(1) result <- AmigaFFH::interpretIFFChunk(result)[[1]] @@ -697,19 +695,16 @@ setGeneric("write.sample", function(sample, filename, what = c("wav", "8svx", "r #' installed in order to write 8svx files. #' @returns Saves the audio to a file, but returns nothing. #' @examples -#' \dontrun{ #' data("mod.intro") -#' +#' #' ## Export the second sample of mod.intro as a wav file: -#' write.sample(PTSample(mod.intro, 2), "snaredrum.wav", "wav") +#' write.sample(PTSample(mod.intro, 2), tempfile(fileext = ".wav"), "wav") #' #' ## Export the second sample of mod.intro as an 8svx file: -#' write.sample(PTSample(mod.intro, 2), "snaredrum.iff", "8svx") +#' write.sample(PTSample(mod.intro, 2), tempfile(fileext = ".iff"), "8svx") #' #' ## Export the second sample of mod.intro as a raw file: -#' write.sample(PTSample(mod.intro, 2), "snaredrum.raw", "raw") -#' } -#' +#' write.sample(PTSample(mod.intro, 2), tempfile(fileext = ".raw"), "raw") #' @family sample.operations #' @author Pepijn de Vries #' @family io.operations diff --git a/R/06PTModule.r b/R/06PTModule.r index e756bd9..f265c77 100644 --- a/R/06PTModule.r +++ b/R/06PTModule.r @@ -1,31 +1,31 @@ validity.PTModule <- function(object) { - if (length(object@pattern.order.length) != 1) return (F) + if (length(object@pattern.order.length) != 1) return (FALSE) if (!(as.integer(object@pattern.order.length) > 0 && - as.integer(object@pattern.order.length) < 129)) return (F) - if (length(object@name) != 20) return (F) - if (length(object@pattern.order) != 128) return (F) - if (length(object@tracker.byte) != 1) return (F) - if (object@tracker.byte != as.raw(0x7F)) return (F) + as.integer(object@pattern.order.length) < 129)) return (FALSE) + if (length(object@name) != 20) return (FALSE) + if (length(object@pattern.order) != 128) return (FALSE) + if (length(object@tracker.byte) != 1) return (FALSE) + if (object@tracker.byte != as.raw(0x7F)) return (FALSE) # We're only being compatible with ProTracker, which holds 31 samples - if (length(object@samples) != 31) return (F) + if (length(object@samples) != 31) return (FALSE) if (!all(unlist(lapply(object@samples, class)) == "PTSample")) - return (F) - if (!all(unlist(lapply(object@samples, validObject, test = T)))) return (F) + return (FALSE) + if (!all(unlist(lapply(object@samples, validObject, test = TRUE)))) return (FALSE) if (!all(unlist(lapply(object@patterns, class)) == "PTPattern")) - return (F) - if (!all(unlist(lapply(object@patterns, validObject, test = T)))) return (F) - if (length(object@tracker.flag) != 4) return (F) + return (FALSE) + if (!all(unlist(lapply(object@patterns, validObject, test = TRUE)))) return (FALSE) + if (length(object@tracker.flag) != 4) return (FALSE) if (!all(object@tracker.flag == charToRaw("M.K.")) && - !all(object@tracker.flag == charToRaw("M!K!"))) return (F) + !all(object@tracker.flag == charToRaw("M!K!"))) return (FALSE) tf <- all(object@tracker.flag == charToRaw("M!K!")) - if (length(object@patterns) > 64 && !tf) return (F) - if (length(object@patterns) > 100 && tf) return (F) - if (length(object@patterns) < 1) return (F) + if (length(object@patterns) > 64 && !tf) return (FALSE) + if (length(object@patterns) > 100 && tf) return (FALSE) + if (length(object@patterns) < 1) return (FALSE) if (!all(unlist(lapply(object@patterns, class)) == "PTPattern")) - return (F) - if ((max(as.integer(object@pattern.order)) + 1) > length(object@patterns)) return (F) - return (T) + return (FALSE) + if ((max(as.integer(object@pattern.order)) + 1) > length(object@patterns)) return (FALSE) + return (TRUE) } #' The PTModule class @@ -149,7 +149,7 @@ setClass("PTModule", #' scales = list(x = list(relation = "free"))) #' @author Pepijn de Vries #' @export -setMethod("plot", c("PTModule", "missing"), function(x, y, plot.loop.positions = T, ...){ +setMethod("plot", c("PTModule", "missing"), function(x, y, plot.loop.positions = TRUE, ...){ amplitude <- NULL samp_name <- NULL `time (s)` <- NULL @@ -253,7 +253,7 @@ setMethod("playSample", "PTModule", function(x, silence, wait, note, loop, ...){ invisible() }) -setGeneric("read.module", function(file, ignore.validity = F) standardGeneric("read.module")) +setGeneric("read.module", function(file, ignore.validity = FALSE) standardGeneric("read.module")) #' Read a ProTracker module file #' @@ -288,24 +288,23 @@ setGeneric("read.module", function(file, ignore.validity = F) standardGeneric("r #' @returns Returns a `PTModule` object read from the provided ProTracker file #' #' @examples -#' \dontrun{ -#' #' ## first create an module file from example data: #' data("mod.intro") -#' write.module(mod.intro, "intro.mod") +#' +#' f <- tempfile(fileext = ".mod") +#' write.module(mod.intro, f) #' #' ## read the module: -#' mod <- read.module("intro.mod") +#' mod <- read.module(f) #' #' ## or create a connection yourself: -#' con <- file("intro.mod", "rb") +#' con <- file(f, "rb") #' #' ## note that you can also read from URL connections! #' mod2 <- read.module(con) #' #' ## don't forget to close the file: #' close(con) -#' } #' @references #' @family io.operations #' @family module.operations @@ -323,14 +322,14 @@ setMethod("read.module", c("character", "logical"), function(file, ignore.validi #' @aliases read.module,ANY,missing-method #' @export setMethod("read.module", c("ANY", "missing"), function(file, ignore.validity) { - read.module(file, F) + read.module(file, FALSE) }) #' @rdname read.module #' @aliases read.module,character,missing-method #' @export setMethod("read.module", c("ANY", "missing"), function(file, ignore.validity) { - read.module(file, F) + read.module(file, FALSE) }) #' @rdname read.module @@ -446,20 +445,19 @@ setGeneric("write.module", def = function(mod, file){ #' @returns Writes to a module file but returns nothing. #' #' @examples -#' \dontrun{ #' ## get the PTModule object provided with the ProTrackR package #' data("mod.intro") #' +#' f <- tempfile(fileext = ".mod") #' ## save the object as a valid ProTracker module file: -#' write.module(mod.intro, "intro.mod") +#' write.module(mod.intro, f) #' #' ## or create the connection yourself: -#' con <- file("intro2.mod", "wb") +#' con <- file(f, "wb") #' write.module(mod.intro, con) #' #' ## don't forget to close the connection after you're done: #' close(con) -#' } #' @references #' @family io.operations #' @family module.operations @@ -946,7 +944,7 @@ setMethod("deletePattern", c("PTModule", "numeric"), function(x, index){ if (index < 1) stop("Invalid index.") if (index > length(x@patterns)) stop("Index out of range.") if (length(x@patterns) < 2) stop("You can't delete the last pattern table!") - p.order <- patternOrder(x, T) + p.order <- patternOrder(x, TRUE) p.order[p.order == (index - 1)] <- 0 p.order[p.order > (index - 1)] <- p.order[p.order > (index - 1)] - 1 x@patterns[index] <- NULL @@ -1009,7 +1007,7 @@ setGeneric("appendPattern", function(x, pattern){ setMethod("appendPattern", c("PTModule", "PTPattern"), function(x, pattern){ max.patterns <- ifelse(all(x@tracker.flag == charToRaw("M!K!")), 100, 64) if (length(x@patterns) >= max.patterns) stop ("Can't insert pattern. Module already holds maximum number of patterns.") - p.order <- patternOrder(x, full = T) + p.order <- patternOrder(x, full = TRUE) p.order.len <- patternOrderLength(x) x@patterns[[length(x@patterns) + 1]] <- pattern if (p.order.len == 128){ @@ -1109,7 +1107,7 @@ setGeneric("clearSong", function(mod) standardGeneric("clearSong")) #' @export setMethod("clearSong", "PTModule", function(mod){ mod@patterns <- list(new("PTPattern")) - suppressWarnings(patternOrder(mod, T) <- 0) + suppressWarnings(patternOrder(mod, TRUE) <- 0) return(mod) }) @@ -1174,7 +1172,6 @@ setGeneric("fix.PTModule", function(mod, verbose) standardGeneric("fix.PTModule" #' @note In the current version, pattern data itself is not checked for #' non-conformaties nor is it fixed. #' @examples -#' \dontrun{ #' data("mod.intro") #' #' ## Let's do something illegal and destroy mod.intro: @@ -1189,12 +1186,11 @@ setGeneric("fix.PTModule", function(mod, verbose) standardGeneric("fix.PTModule" #' mod.intro <- fix.PTModule(mod.intro) #' #' ## See, it's all OK again: -#' validObject(mod.intro, TRUE) -#' } +#' validObject(mod.intro, FALSE) #' @family module.operations #' @author Pepijn de Vries #' @export -setMethod("fix.PTModule", c("PTModule", "logical"), function(mod, verbose = T){ +setMethod("fix.PTModule", c("PTModule", "logical"), function(mod, verbose = TRUE){ if (verbose) cat("Check and fix if pattern.order.length is a raw of length 1\n") mod@pattern.order.length <- as.raw(mod@pattern.order.length[[1]]) if (verbose) cat("Check and fix if pattern.order.length value is out of range (1-128)\n") @@ -1273,7 +1269,7 @@ setMethod("fix.PTModule", c("PTModule", "logical"), function(mod, verbose = T){ } ## Pattern data itself is currently not checked and fixed - if (verbose && validObject(mod, T)) cat("Module successfully fixed\n") else + if (verbose && validObject(mod, TRUE)) cat("Module successfully fixed\n") else cat("Fixing module failed\n") return(mod) }) @@ -1282,7 +1278,7 @@ setMethod("fix.PTModule", c("PTModule", "logical"), function(mod, verbose = T){ #' @aliases fix.PTModule,PTModule,missing-method #' @export setMethod("fix.PTModule", c("PTModule", "missing"), function(mod){ - fix.PTModule(mod, T) + fix.PTModule(mod, TRUE) }) #' @rdname as.raw @@ -1295,7 +1291,7 @@ setMethod("as.raw", "PTModule", function(x){ return(result) }) -setGeneric("rawToPTModule", function(x, ignore.validity = F) standardGeneric("rawToPTModule")) +setGeneric("rawToPTModule", function(x, ignore.validity = FALSE) standardGeneric("rawToPTModule")) #' Convert a vector of raw data into a PTModule object #' @@ -1320,7 +1316,6 @@ setGeneric("rawToPTModule", function(x, ignore.validity = F) standardGeneric("ra #' thrown when invalidity occurs. #' @returns returns a [`PTModule-class`] object. #' @examples -#' \dontrun{ #' ## convert the example mod into raw data #' data("mod.intro") #' mod.raw <- as.raw(mod.intro) @@ -1330,7 +1325,6 @@ setGeneric("rawToPTModule", function(x, ignore.validity = F) standardGeneric("ra #' #' ## In this case the result is identical to the original: #' identical(mod.restored, mod.intro) -#' } #' @family module.operations #' @family raw.operations #' @author Pepijn de Vries diff --git a/R/07PTBlock.r b/R/07PTBlock.r index f71fc75..2e2ad2a 100644 --- a/R/07PTBlock.r +++ b/R/07PTBlock.r @@ -4,7 +4,7 @@ if (any(unlist(lapply(object, function(x) !("PTCell" %in% class(x)))))) stop("Not a valid PTBlock") if (any(unlist(lapply(object, length)) != 1)) stop("Not a valid PTBlock") if (any(!unlist(lapply(object, validObject)))) stop("Not a valid PTBlock") - return(T) + return(TRUE) } setGeneric("PTBlock", function(pattern, row, track) standardGeneric("PTBlock")) @@ -69,8 +69,8 @@ setMethod("PTBlock", c("PTPattern", "numeric", "numeric"), function(pattern, row index <- as.list(((1:maximumTrackCount)- 1)*4 + 1) lapply(index, function(y) PTCell(x[y:(y+3)])) }) - cells <- matrix(unlist(cells), 64, byrow = T) - return(cells[row, track, drop = F]) + cells <- matrix(unlist(cells), 64, byrow = TRUE) + return(cells[row, track, drop = FALSE]) }) setGeneric("pasteBlock", function(pattern, block, row.start, track.start) standardGeneric("pasteBlock")) @@ -153,5 +153,5 @@ setMethod("pasteBlock", c("PTPattern", "matrix", "numeric", "numeric"), # test if the block is valid: .validity.PTBlock(block) return(matrix(unlist(lapply(t(block), as.raw)), - nrow(block), 4*ncol(block), byrow = T)) + nrow(block), 4*ncol(block), byrow = TRUE)) } diff --git a/R/08coercion.r b/R/08coercion.r index 04c5a6e..f974ac8 100644 --- a/R/08coercion.r +++ b/R/08coercion.r @@ -267,7 +267,7 @@ setMethod("PTTrack", c("matrix", "missing", "missing"), function(x){ setMethod("PTTrack", c("character", "missing", "missing"), function(x){ if (length(x) != maximumPatternTableRowCount) stop ("x should be a vector of 64 character strings") cells <- PTCell(x) - raw.dat <- matrix(unlist(lapply(cells, as.raw)), ncol = 4, byrow = T) + raw.dat <- matrix(unlist(lapply(cells, as.raw)), ncol = 4, byrow = TRUE) return (PTTrack(raw.dat)) }) @@ -387,7 +387,7 @@ setMethod("PTPattern", c("matrix", "missing"), function(x){ { if (any(dim(x) != c(maximumPatternTableRowCount, maximumTrackCount))) stop ("x should be a matrix of 64 by 4 holding character strings") cells <- PTCell(as.character(t(x))) - raw.dat <- matrix(unlist(lapply(cells, as.raw)), ncol = 4*maximumTrackCount, byrow = T) + raw.dat <- matrix(unlist(lapply(cells, as.raw)), ncol = 4*maximumTrackCount, byrow = TRUE) return (PTPattern(raw.dat)) } if (typeof(x) == "raw") @@ -497,7 +497,7 @@ setMethod("PTSample", c("Wave", "missing"), function(x){ temp <- rbind(temp, rep(delta*(2^x@bit)/(256), 2)) } x <- new("PTSample", - left = delta + as.integer(apply(temp, 1, function(x) mean(x, na.rm = T))/(2^(x@bit - 8))), + left = delta + as.integer(apply(temp, 1, function(x) mean(x, na.rm = TRUE))/(2^(x@bit - 8))), wlooplen = as.raw(c(0, 1))) rm(temp) diff --git a/R/09playing_routines.r b/R/09playing_routines.r index af1734b..a94a237 100644 --- a/R/09playing_routines.r +++ b/R/09playing_routines.r @@ -1,23 +1,4 @@ -## https://pastebin.com/pg95YduC -## https://bel.fi/alankila/modguide/interpolate.txt -## XXX max output rate differs per channel still need to try to confirm that?: -## https://eab.abime.net/showthread.php?t=70783 - -## The amiga hardware reference manual: -## https://archive.org/stream/Amiga_Hardware_Reference_Manual_1985_Commodore_a/Amiga_Hardware_Reference_Manual_1985_Commodore_a_djvu.txt -## The minimum period value you should use is 124 -## ticks per sample NTSC (123 PAL) and the maximum is 65535. -## These limits apply to both PAL and NTSC machines. -## It doesn't say if these are hard limits, or whether these -## are just the specs, that you possible go beyond. -## in de WINUAE emulator lijkt de period value lager te kunnen dan de 124 -## each channel different limit: https://eab.abime.net/showthread.php?t=70783 -## WINUAE seem to use noteToPeriod("B-3") as the limit for all channels - -## Olav Sorensen: -## Porta effects have period limits of 113 - 856 hard coded in ProTracker -## Other effect have no limits coded in ProTracker, the limit of 113 is also a 'hard' physical limit on a real Amiga -setGeneric("playMod", function(mod, wait = T, ...) standardGeneric("playMod")) +setGeneric("playMod", function(mod, wait = TRUE, ...) standardGeneric("playMod")) #' Play PTModule objects #' @@ -43,11 +24,11 @@ setGeneric("playMod", function(mod, wait = T, ...) standardGeneric("playMod")) #' @returns A [`tuneR::Wave`] object, generated from the #' `mod` object, is returned. #' @examples -#' \dontrun{ -#' data("mod.intro") +#' if (interactive()) { +#' data("mod.intro") #' -#' ## play the module and capture the audio Wave -#' wav <- playMod(mod.intro) +#' ## play the module and capture the audio Wave +#' wav <- playMod(mod.intro) #' } #' @author Pepijn de Vries #' @family play.audio.routines @@ -60,14 +41,14 @@ setMethod("playMod", "PTModule", function(mod, wait, ...){ return(wav) }) -setGeneric("playWave", function(wave, wait = T) standardGeneric("playWave")) +setGeneric("playWave", function(wave, wait = TRUE) standardGeneric("playWave")) #' Play Wave objects #' #' Use the command line [`audio::play`] function from the #' `audio` package to play [`tuneR::Wave`] objects. #' -#' As the [`tuneR`] package play-function relies on external +#' As the `tuneR` package play-function relies on external #' players, this method is provided as a convenient approach to play #' samples in the R console, using the `audio` package. Wave #' objects are played at the rate as specified in the object. Of course @@ -86,13 +67,13 @@ setGeneric("playWave", function(wave, wait = T) standardGeneric("playWave")) #' executed while playing. #' @returns Returns an [`audio::$.audioInstance`]. #' @examples -#' \dontrun{ -#' data(mod.intro) +#' if (interactive()) { +#' data(mod.intro) #' -#' ## PTSample objects can also be -#' ## played with this function as they -#' ## are a child of the Wave object: -#' playWave(PTSample(mod.intro, 2)) +#' ## PTSample objects can also be +#' ## played with this function as they +#' ## are a child of the Wave object: +#' playWave(PTSample(mod.intro, 2)) #' } #' @family play.audio.routines #' @author Pepijn de Vries @@ -119,8 +100,8 @@ setMethod("playWave", "Wave", function(wave, wait){ setMethod("playWave", "WaveMC", function(wave, wait){ ## drop the center channels and mix the left and right channels: if (is.null(colnames(wave@.Data))) colnames(wave@.Data) <- tuneR::MCnames$name[1:ncol(wave@.Data)] - wave <- Wave(left = rowMeans(wave@.Data[,grepl("L", colnames(wave@.Data)), drop = F]), - right = rowMeans(wave@.Data[,grepl("R", colnames(wave@.Data)), drop = F]), + wave <- Wave(left = rowMeans(wave@.Data[,grepl("L", colnames(wave@.Data)), drop = FALSE]), + right = rowMeans(wave@.Data[,grepl("R", colnames(wave@.Data)), drop = FALSE]), bit = wave@bit, samp.rate = wave@samp.rate, pcm = wave@pcm) @@ -240,17 +221,15 @@ setGeneric("modToWave", #' `mod` object is returned. A [`tuneR::WaveMC`] object is returned when #' the `mix` argument is set to `FALSE`. #' @examples -#' \dontrun{ #' data(mod.intro) #' wav <- modToWave(mod.intro) -#' } #' @author Pepijn de Vries #' @family module.operations #' @export setMethod("modToWave", "PTModule", function(mod, video, target.rate, target.bit, stereo.separation, low.pass.filter, tracks, mix, ...){ mix <- as.logical(mix)[[1]] video <- match.arg(video) - verbose <- T + verbose <- TRUE tracks <- sort(unique((1:maximumTrackCount)[tracks])) moreArgs <- list(...) if ("verbose" %in% names(moreArgs)) verbose <- moreArgs[["verbose"]] @@ -280,8 +259,8 @@ setMethod("modToWave", "PTModule", function(mod, video, target.rate, target.bit, result <- matrix(rowMeans(result), ncol = 1) result <- cbind(result, result) } else { - result <- cbind(rowMeans(result[, tracks %in% c(1,4), drop = F]), - rowMeans(result[, tracks %in% c(2,3), drop = F])) + result <- cbind(rowMeans(result[, tracks %in% c(1,4), drop = FALSE]), + rowMeans(result[, tracks %in% c(2,3), drop = FALSE])) } } result <- (((2^(target.bit - 8)))*(256/255) - (1/255))*result @@ -322,8 +301,8 @@ setGeneric("playingtable", speed = 6, tempo = 0x7D, video = c("PAL", "NTSC"), - play.once = T, - verbose = T){ + play.once = TRUE, + verbose = TRUE){ standardGeneric("playingtable") }) @@ -400,10 +379,8 @@ setGeneric("playingtable", #' order. Information contained in the returned table is described in the #' 'Details' section #' @examples -#' \dontrun{ #' data(mod.intro) #' pt <- playingtable(mod.intro) -#' } #' @author Pepijn de Vries #' @family module.operations #' @export @@ -432,7 +409,7 @@ setMethod("playingtable", "PTModule", function(mod, verbose <- as.logical(verbose[[1]]) remember.start.pos <- starting.position - filter_fin <- F + filter_fin <- FALSE threshold <- 0.1/44100 # first create tables per pattern: if (verbose) cat("Processing pattern tables...") @@ -566,9 +543,9 @@ setMethod("playingtable", "PTModule", function(mod, # the highest track has priority, remainder is ignored. # Dxy effect left of Bxy effects should be ignored. right_of_Bxy <- t(apply(fx, 1, function(x){ - result <- rep(T, length(x)) + result <- rep(TRUE, length(x)) bright <- suppressWarnings(max(which(x == as.raw(0x0b)))) - if (!is.infinite(bright)) result[1:bright] <- F + if (!is.infinite(bright)) result[1:bright] <- FALSE return(result) })) result$pattern.break <- .specificEffectMagnitudes(as.raw(0x0D), @@ -613,7 +590,7 @@ setMethod("playingtable", "PTModule", function(mod, cum_duration <- 0 vblank_duration <- ifelse(match.arg(video) == "PAL", 1/50, 1/60) # flag indicating for each channel whether there is a pattern loop active: - loop.on <- rep(F, maximumTrackCount) + loop.on <- rep(FALSE, maximumTrackCount) # counter for pattern loops in each channel. Will count down to zero when # a loop is active, and will continue playing once it reaches zero. # when multiple loop ends are positioned in the same row, all @@ -629,7 +606,7 @@ setMethod("playingtable", "PTModule", function(mod, pat_tab$row <- 1:maximumPatternTableRowCount ## look for loop-starts (E60) from top to bottom using a while loop. - loops <- pat_tab[,grepl("loop.track", names(pat_tab), fixed = T)] + loops <- pat_tab[,grepl("loop.track", names(pat_tab), fixed = TRUE)] loop.pos <- which(apply(loops, 1, function(x) any(!is.na(x)))) pos <- 1 + row.skip loop.index <- ifelse (length(loop.pos) > 0, @@ -646,20 +623,20 @@ setMethod("playingtable", "PTModule", function(mod, row.skip <- 0 if (any(!is.na(pat_tab_ext$position.jump)) || any(!is.na(pat_tab_ext$pattern.break))) break - if (any(loops[loop.pos[loop.index],] > 0, na.rm = T)) + if (any(loops[loop.pos[loop.index],] > 0, na.rm = TRUE)) { ## if loop is currently off, set the counter... loop.counter[which(!loop.on & loops[loop.pos[loop.index],] > 0)] <- unlist(loops[loop.pos[loop.index], which(!loop.on & loops[loop.pos[loop.index],] > 0)]) + 1 ## ... and turn the loop on - loop.on[which(!loop.on & loops[loop.pos[loop.index],] > 0)] <- T + loop.on[which(!loop.on & loops[loop.pos[loop.index],] > 0)] <- TRUE ## When the loop is turned on, subtract 1 from the counter loop.counter[which(loop.on & loops[loop.pos[loop.index],] > 0)] <- loop.counter[which(loop.on & loops[loop.pos[loop.index],] > 0)] - 1 ## If the counter reaches 0, turn off the loop - loop.on[loop.on & loop.counter == 0] <- F + loop.on[loop.on & loop.counter == 0] <- FALSE pos <- suppressWarnings(max(loop.start.pos[which(loop.on & loops[loop.pos[loop.index],] > 0)])) if (is.infinite(pos) || all(!loop.on)) @@ -670,7 +647,7 @@ setMethod("playingtable", "PTModule", function(mod, { loop.index <- min(which(loop.pos > pos)) } - } else if (any(loops[loop.pos[loop.index],] == 0, na.rm = T)) + } else if (any(loops[loop.pos[loop.index],] == 0, na.rm = TRUE)) { loop.start.pos[which(loops[loop.pos[loop.index],] == 0)] <- loop.pos[loop.index] pos <- loop.pos[loop.index] + 1 @@ -801,7 +778,7 @@ setMethod("playingtable", "PTModule", function(mod, return (pat_tab) } -.generate.channel.data <- function(mod, pt, track.nr, target.rate, video = c("PAL", "NTSC"), low.pass.filter = T, verbose = F) +.generate.channel.data <- function(mod, pt, track.nr, target.rate, video = c("PAL", "NTSC"), low.pass.filter = TRUE, verbose = FALSE) { if (verbose) cat(paste("Track ", track.nr, ":\n", sep ="")) video <- match.arg(video) @@ -1029,7 +1006,7 @@ setMethod("playingtable", "PTModule", function(mod, tremolo.pos.start[tremolo.pos.start == 1] <- NA tremolo.pos.start[1][is.na(tremolo.pos.start[1])] <- 0 tremolo.pos.start <- .fill.parameter(tremolo.pos.start, is.na(tremolo.pos.start), function(x, y, z){rep(z, times = y - x + 1)}) - tremolo.pos[is.na(tremolo.pos)] <- .fill.parameter(tremolo.pos[is.na(tremolo.pos)], rep(T, sum(is.na(tremolo.pos))), + tremolo.pos[is.na(tremolo.pos)] <- .fill.parameter(tremolo.pos[is.na(tremolo.pos)], rep(TRUE, sum(is.na(tremolo.pos))), function(x, y, z, tck){ trm <- integer(y-x) sel <- tck[is.na(tremolo.pos)][x:y] != 1 @@ -1112,7 +1089,7 @@ setMethod("playingtable", "PTModule", function(mod, target2 <-.fill.parameter(target2, is.na(target2), function(x, y, z){rep(z, times = y - x + 1)}) rm(snr) - potential.target <- rep(T, nrow(result)) + potential.target <- rep(TRUE, nrow(result)) potential.target[result$note == "---" | result$tick != 1] <- NA ############################################## ## 3xy Porta to note end initializing targets @@ -1146,12 +1123,12 @@ setMethod("playingtable", "PTModule", function(mod, ## tnr2 = a modified version of 'target_not_reached', taking ## into account whether the target has been reset - tnr2 <- rep(T, nrow(result)) + tnr2 <- rep(TRUE, nrow(result)) ## once a target is reached porta to note should stop sliding ## if target is not reached but a sample is retriggered, the target should not be reset! if (any(effect_sel)) { - target_not_reached <- rep(F, nrow(result)) + target_not_reached <- rep(FALSE, nrow(result)) target.finetune <- as.numeric(substr(target[!is.na(target)], 5, 6)) target.finetune <- unlist(lapply(as.list(as.numeric(substr(target[!is.na(target)], 5, 6))), function(x) ifelse(x == 0, 0, fineTune(mod@samples[[x]])))) temp <- noteToPeriod(substr(target[!is.na(target)], 1, 3), finetune = target.finetune) @@ -1162,28 +1139,28 @@ setMethod("playingtable", "PTModule", function(mod, rm(target.finetune) ## If it's not known whether the target is reached, don't do anything yet!: - unknown_target <- which(result$retrigger.sample == 1 & c(F, is.na(target_not_reached[-nrow(result)])) & !effect_sel) + unknown_target <- which(result$retrigger.sample == 1 & c(FALSE, is.na(target_not_reached[-nrow(result)])) & !effect_sel) target[unknown_target] <- "???" - target_not_reached[is.na(target_not_reached)] <- T + target_not_reached[is.na(target_not_reached)] <- TRUE ## sample is retriggered and target is reached and effect is not 3xy or 5xy: ## reset the target: - reset_target <- which(result$retrigger.sample == 1 & c(F, !target_not_reached[-nrow(result)]) & !effect_sel) + reset_target <- which(result$retrigger.sample == 1 & c(FALSE, !target_not_reached[-nrow(result)]) & !effect_sel) target[reset_target] <- target2[reset_target] ## if no new target is specified and the target is reached don't slide repeat{ tnr2 <- rep(NA, nrow(result)) - tnr2[!(is.na(potential.target))] <- T + tnr2[!(is.na(potential.target))] <- TRUE tnr2 <- .fill.parameter(tnr2, is.na(potential.target), function (x,y,z, tnr, fx){ - res <- rep(T, y - x + 1) + res <- rep(TRUE, y - x + 1) res[fx[x:y]] <- as.logical(cumprod(tnr[x:y][fx[x:y]])) res }, target_not_reached, effect_sel) pt <- potential.target - pt[is.na(pt)] <- F - potential.target[which(pt & !effect_sel & !c(T,tnr2[-length(tnr2)]))] <- NA + pt[is.na(pt)] <- FALSE + potential.target[which(pt & !effect_sel & !c(TRUE,tnr2[-length(tnr2)]))] <- NA if (length(which(pt)) == length(which(potential.target))) break } } @@ -1233,7 +1210,7 @@ setMethod("playingtable", "PTModule", function(mod, result$period <- .fill.parameter(result$period, effect_sel, function(x, y, z, mag){ if (is.na(z)) return(rep(NA, y - x + 1)) - while (T) + while (TRUE) { cums <- cumsum(mag[x:y]) res <- bitwAnd(0xFFF, cums + z) @@ -1276,7 +1253,7 @@ setMethod("playingtable", "PTModule", function(mod, function(x, y, z, mag){ if (is.na(z)) return(rep(NA, y - x + 1)) if (z > 856) z <- 856 - while (T) + while (TRUE) { cums <- cumsum(mag[x:y]) res <- cums + z @@ -1316,7 +1293,7 @@ setMethod("playingtable", "PTModule", function(mod, result$period <- .fill.parameter(result$period, effect_sel, function(x, y, z, mag){ if (is.na(z)) return(rep(NA, y - x + 1)) - while (T) + while (TRUE) { cums <- cumsum(mag[x:y]) res <- cums + z @@ -1359,9 +1336,9 @@ setMethod("playingtable", "PTModule", function(mod, ############################################## out.of.range <- rep(NA, nrow(result)) - out.of.range[1] <- F - out.of.range[result$retrigger.sample == 1] <- F - out.of.range[result$period > 856] <- T + out.of.range[1] <- FALSE + out.of.range[result$retrigger.sample == 1] <- FALSE + out.of.range[result$period > 856] <- TRUE out.of.range <- .fill.parameter(out.of.range, is.na(out.of.range), function(x, y, z){rep(z, times = y - x + 1)}) ## XXX the value of 0xffff does not seem to be correct ## the value seem to differ for different test cases, but is always high. @@ -1424,7 +1401,7 @@ setMethod("playingtable", "PTModule", function(mod, vibrato.pos.start[vibrato.pos.start == 1] <- NA vibrato.pos.start[1][is.na(vibrato.pos.start[1])] <- 0 vibrato.pos.start <- .fill.parameter(vibrato.pos.start, is.na(vibrato.pos.start), function(x, y, z){rep(z, times = y - x + 1)}) - vibrato.pos[is.na(vibrato.pos)] <- .fill.parameter(vibrato.pos[is.na(vibrato.pos)], rep(T, sum(is.na(vibrato.pos))), + vibrato.pos[is.na(vibrato.pos)] <- .fill.parameter(vibrato.pos[is.na(vibrato.pos)], rep(TRUE, sum(is.na(vibrato.pos))), function(x, y, z, tck){ vib <- integer(y-x) sel <- tck[is.na(vibrato.pos)][x:y] != 1 @@ -1535,13 +1512,13 @@ setMethod("playingtable", "PTModule", function(mod, snr <- (result$sample.nr.original != 0) snr[result$retrigger.sample != 1] <- NA - snr[result$retrigger.sample == 1 & effect_sel] <- T - snr[1][is.na(snr[1])] <- F + snr[result$retrigger.sample == 1 & effect_sel] <- TRUE + snr[1][is.na(snr[1])] <- FALSE snr <- .fill.parameter(snr, is.na(snr), function(x, y, z){rep(z, times = y - x + 1)}) mod_bool <- rep(NA, nrow(result)) - mod_bool[with(result, note == "---" & effect_sel)] <- T - mod_bool[with(result, (retrigger.sample == 1 | effect_sel) & sample.nr.original > 0)] <- F + mod_bool[with(result, note == "---" & effect_sel)] <- TRUE + mod_bool[with(result, (retrigger.sample == 1 | effect_sel) & sample.nr.original > 0)] <- FALSE mod_bool <- .fill.parameter(mod_bool, is.na(mod_bool), function(x, y, z){rep(z, times = y - x + 1)}) effect_sel2 <- with(result, !mod_bool & diff(c(-999, snr)) != 0 & sample.nr.original == 0 & note != "---" & !effect_sel & tick == 1) | with(result, effect_sel & sample.nr.original == 0 & tick == 1) rm(mod_bool) @@ -1560,7 +1537,7 @@ setMethod("playingtable", "PTModule", function(mod, effect.fill <- rep(NA, nrow(result)) effect.fill[with(result, note != "---" & sample.nr.original != 0)] <- effect_sel[with(result, note != "---" & sample.nr.original != 0)] - effect.fill[effect_sel] <- T + effect.fill[effect_sel] <- TRUE effect.fill <- .fill.parameter(effect.fill, is.na(effect.fill), function(x, y, z){rep(z, times = y - x + 1)}) base.magnitude[(result$sample.nr.original > 0 & !effect_sel) | (result$note != "---" & !effect.fill)] <- 0 @@ -1593,19 +1570,19 @@ setMethod("playingtable", "PTModule", function(mod, ## Sample switching starts here. not implemented correctly yet result$sample.switch <- NA - result$sample.switch[result$retrigger.sample == 1] <- F + result$sample.switch[result$retrigger.sample == 1] <- FALSE result$sample.switch[diff(c(0, result$sample.nr)) != 0 & result$retrigger.sample != 1 & - result$sample.nr != 0] <- T - result$sample.switch[1][is.na(result$sample.switch[1])] <- F + result$sample.nr != 0] <- TRUE + result$sample.switch[1][is.na(result$sample.switch[1])] <- FALSE result$sample.switch <- .fill.parameter(result$sample.switch, is.na(result$sample.switch), function(x, y, z){rep(z, times = y - x + 1)}) ## take one line before to know from which sample to switch from - samp.switch <- subset(result, result$sample.switch | c(result$sample.switch[-1], F)) + samp.switch <- subset(result, result$sample.switch | c(result$sample.switch[-1], FALSE)) if(nrow(samp.switch) > 0) { - samp.switch$index <- which(result$sample.switch | c(result$sample.switch[-1], F)) + samp.switch$index <- which(result$sample.switch | c(result$sample.switch[-1], FALSE)) group.start <- diff(c(-999, samp.switch$index)) > 1 samp.switch$group <- NA samp.switch$group[group.start] <- 1:sum(group.start) @@ -1626,7 +1603,7 @@ setMethod("playingtable", "PTModule", function(mod, ((samp.group$sample.pos[samp.group$sample.pos > (ls + 1)] - (ls + 1)) %% loopLength(sample.from)) + ls + 1 samp.group$sample.nr[-1][diff(samp.group$sample.pos) >= 0] <- samp.group$sample.nr[1] - samp.group$sample.switch <- c(F, diff(samp.group$sample.pos) < 0) + samp.group$sample.switch <- c(FALSE, diff(samp.group$sample.pos) < 0) } else { sl <- sampleLength(sample.from) @@ -1646,7 +1623,7 @@ setMethod("playingtable", "PTModule", function(mod, ## current implementation of sample switching ends here... - resamp_sel <- result$retrigger.sample == 1 | c(F, result$period[-nrow(result)] != result$period[-1]) + resamp_sel <- result$retrigger.sample == 1 | c(FALSE, result$period[-nrow(result)] != result$period[-1]) result$resamp.start <- NA result$resamp.start[resamp_sel] <- 1:sum(resamp_sel) result$resamp.start <- .fill.parameter(result$resamp.start, !resamp_sel, function(x, y, z){rep(z, times = y - x + 1)}) @@ -1657,7 +1634,7 @@ setMethod("playingtable", "PTModule", function(mod, resamp.table <- merge(resamp.table, stats::aggregate(cbind(sample.nr, sample.rate, sample.pos)~resamp.start, result, function(x) x[[1]])) rm(duration) - resamp.agg <- stats::aggregate(row.nr~sample.nr+target.nsamples+sample.rate+sample.pos, cbind(resamp.table, row.nr = 1:nrow(resamp.table)), function(x) x, simplify = F) + resamp.agg <- stats::aggregate(row.nr~sample.nr+target.nsamples+sample.rate+sample.pos, cbind(resamp.table, row.nr = 1:nrow(resamp.table)), function(x) x, simplify = FALSE) resamp.order <- lapply(as.list(1:nrow(resamp.table)), function(x) which(unlist(lapply(resamp.agg$row.nr, function(y) x %in% y)))) @@ -1708,7 +1685,7 @@ setMethod("playingtable", "PTModule", function(mod, sel_filter <- as.vector(unlist(apply(result, 1, function(x){ rep(x["filter"], as.integer(x["target.nsamples"])) }))) - sel_filter <- grepl("TRUE", sel_filter, fixed = T) + sel_filter <- grepl("TRUE", sel_filter, fixed = TRUE) ## "LED" filter butterworth <- signal::butter(2, 3275/target.rate, "low") channel[sel_filter] <- signal::filter(butterworth, channel[sel_filter]) diff --git a/R/11MODPlugHelpers.r b/R/10MODPlugHelpers.r similarity index 93% rename from R/11MODPlugHelpers.r rename to R/10MODPlugHelpers.r index cbfa79d..c3ac0b9 100644 --- a/R/11MODPlugHelpers.r +++ b/R/10MODPlugHelpers.r @@ -23,7 +23,6 @@ #' @name MODPlugToPTPattern #' @rdname MODPlugToPTPattern #' @examples -#' \dontrun{ #' ## This is what Mod Plug Pattern data looks like on #' ## the system's clipboard: #' modPlugPattern <- c("ModPlug Tracker MOD", @@ -103,7 +102,6 @@ #' ## we can also only import the first 10 lines as a #' ## PTBlock: #' blk <- MODPlugToPTPattern(modPlugPattern[1:10], "PTBlock") -#' } #' @author Pepijn de Vries #' @family MODPlug.operations #' @family pattern.operations @@ -119,8 +117,8 @@ MODPlugToPTPattern <- function(text = NULL, what = c("PTPattern", "PTBlock")) { result <- utils::read.table(text = text[-1], sep = "|", comment.char = "'")[,-1] # replace dots and spaces by dashes: - result <- gsub(" ", "-", as.matrix(result), fixed = T) - result <- gsub(".", "-", as.matrix(result), fixed = T) + result <- gsub(" ", "-", as.matrix(result), fixed = TRUE) + result <- gsub(".", "-", as.matrix(result), fixed = TRUE) # remove information that is not used by ProTracker result <- apply(result, 2, function(x) paste0(substr(x, 1, 5), substr(x, 9, 11))) @@ -129,21 +127,21 @@ MODPlugToPTPattern <- function(text = NULL, what = c("PTPattern", "PTBlock")) { result <- suppressWarnings(apply(result, 2, function(x) paste0(substr(x, 1, 2), as.integer(substr(x, 3, 3)) - 3, substr(x, 4, 8)))) - result <- gsub("NA", "-", result, fixed = T) + result <- gsub("NA", "-", result, fixed = TRUE) result <- apply(result, 2, function(x) paste0(substr(x, 1, 3), - gsub("-", "0", substr(x, 4, 8), fixed = T))) + gsub("-", "0", substr(x, 4, 8), fixed = TRUE))) # MODPlug uses decimal numbers to represent sample numbers # ProTracker uses hexadecimals: result <- suppressWarnings(apply(result, 2, function(x) paste0(substr(x, 1, 3), sprintf("%02X", as.integer(substr(x, 4, 5))), substr(x, 6, 8)))) - result <- gsub("NA", "--", result, fixed = T) + result <- gsub("NA", "--", result, fixed = TRUE) result <- apply(result, 1, function(x){ lapply(1:length(x), function(y) PTCell(x[y])) }) - result <- matrix(unlist(result), length(result), byrow = T) + result <- matrix(unlist(result), length(result), byrow = TRUE) if (what == "PTPattern") { pat <- new("PTPattern") @@ -178,7 +176,6 @@ MODPlugToPTPattern <- function(text = NULL, what = c("PTPattern", "PTBlock")) { #' @name PTPatternToMODPlug #' @rdname PTPatternToMODPlug #' @examples -#' \dontrun{ #' ## get some pattern data #' #' pattern <- PTPattern(mod.intro, 1) @@ -193,37 +190,36 @@ MODPlugToPTPattern <- function(text = NULL, what = c("PTPattern", "PTBlock")) { #' ## If you want to handle the pattern data #' ## in R: #' -#' patModPlug <- PTPatternToMODPlug(pattern, F) +#' patModPlug <- PTPatternToMODPlug(pattern, FALSE) #' #' ## We can do the same with a block: #' #' block <- PTBlock(pattern, 1:10, 2:3) #' PTPatternToMODPlug(block) -#' } #' @author Pepijn de Vries #' @family MODPlug.operations #' @family pattern.operations #' @export -PTPatternToMODPlug <- function(x, to.clipboard = T) { +PTPatternToMODPlug <- function(x, to.clipboard = TRUE) { if (!("PTPattern" %in% class(x)) && !.validity.PTBlock(x)) stop ("x is neither a PTPattern nor a PTBlock object.") # convert the information that is provided into a matrix of characters # and work with that. - if (!("PTPattern" %in% class(x))) { + if (inherits(x, "PTPattern")) { pat <- as.character(x) } else { pat <- apply(x, 2, function(y) unlist(lapply(y, function(z) as.character(z)))) } - pat <- gsub(" ", "", pat, fixed = T) + pat <- gsub(" ", "", pat, fixed = TRUE) pat <- suppressWarnings(apply(pat, 2, function(y) paste0(substr(y, 1, 2), as.character(as.integer(substr(y, 3, 3)) + 3), substr(y, 4, 8)))) - pat <- gsub("NA", "-", pat, fixed = T) + pat <- gsub("NA", "-", pat, fixed = TRUE) pat <- suppressWarnings(apply(pat, 2, function(y) paste0(substr(y, 1, 3), sprintf("%02i", as.integer(paste0("0x", substr(y, 4, 5)))), substr(y, 6, 8)))) - pat <- gsub("NA", "--", pat, fixed = T) - pat <- gsub("(?!\\A)\\G0|(?=0{2,})0", ".", pat, perl = T) - pat <- gsub("(?!\\A)\\G-|(?=-{2,})-", ".", pat, perl = T) + pat <- gsub("NA", "--", pat, fixed = TRUE) + pat <- gsub("(?!\\A)\\G0|(?=0{2,})0", ".", pat, perl = TRUE) + pat <- gsub("(?!\\A)\\G-|(?=-{2,})-", ".", pat, perl = TRUE) pat <- apply(pat, 2, function(y) paste0(substr(y, 1, 5), "...", substr(y, 6, 8))) pat <- apply(pat, 2, function(y) paste0("|", y)) pat <- apply(pat, 1, paste0, collapse = "") diff --git a/R/10ModArchiveHelpers.r b/R/10ModArchiveHelpers.r deleted file mode 100644 index 0946635..0000000 --- a/R/10ModArchiveHelpers.r +++ /dev/null @@ -1,657 +0,0 @@ -genre.table <- read.table(text = " -genre, genre.id - unset, unset - Alternative, 48 - Gothic, 38 - Grunge, 103 - Metal - Extreme, 37 - Metal (general), 36 - Punk, 35 - Chiptune, 54 - Demo Style, 55 - One Hour Compo, 53 - Chillout, 106 - Electronic - Ambient, 2 - Electronic - Breakbeat, 9 - Electronic - Dance, 3 - Electronic - Drum and Bass, 6 - Electronic - Gabber, 40 - Electronic - Hardcore, 39 - Electronic - House, 10 - Electronic - IDM, 99 - Electronic - Industrial, 34 - Electronic - Jungle, 60 - Electronic - Minimal, 101 - Electronic - Other, 100 - Electronic - Progressive, 11 - Electronic - Rave, 65 - Electronic - Techno, 7 - Electronic (general), 1 - Trance - Acid, 63 - Trance - Dream, 67 - Trance - Goa, 66 - Trance - Hard, 64 - Trance - Progressive, 85 - Trance - Tribal, 70 - Trance (general), 71 - Big Band, 74 - Blues, 19 - Jazz - Acid, 30 - Jazz - Modern, 31 - Jazz (general), 29 - Swing, 75 - Bluegrass, 105 - Classical, 20 - Comedy, 45 - Country, 18 - Experimental, 46 - Fantasy, 52 - Folk, 21 - Fusion, 102 - Medieval, 28 - New Ages, 44 - Orchestral, 50 - Other, 41 - Piano, 59 - Religious, 49 - Soundtrack, 43 - Spiritual, 47 - Video Game, 8 - Vocal Montage, 76 - World, 42 - Ballad, 56 - Disco, 58 - Easy Listening, 107 - Funk, 32 - Pop - Soft, 62 - Pop - Synth, 61 - Pop (general), 12 - Rock - Hard, 14 - Rock - Soft, 15 - Rock (general), 13 - Christmas, 72 - Halloween, 82 - Hip-Hop, 22 - R and B, 26 - Reggae, 27 - Ska, 24 - Soul, 25", header = T, sep = ",", stringsAsFactors = F, strip.white = T) - -#html escape codes - -htmlcodes <- read.table(text = " - char, code - 8364, 'euro' - 32, 'nbsp' - 34, 'quot' - 38, 'amp' - 60, 'lt' - 62, 'gt' - 160, 'nbsp' - 161, 'iexcl' - 162, 'cent' - 163, 'pound' - 164, 'curren' - 165, 'yen' - 166, 'brvbar' - 167, 'sect' - 168, 'uml' - 169, 'copy' - 170, 'ordf' - 172, 'not' - 173, 'shy' - 174, 'reg' - 175, 'macr' - 176, 'deg' - 177, 'plusmn' - 178, 'sup2' - 179, 'sup3' - 180, 'acute' - 181, 'micro' - 182, 'para' - 183, 'middot' - 184, 'cedil' - 185, 'sup1' - 186, 'ordm' - 187, 'raquo' - 188, 'frac14' - 189, 'frac12' - 190, 'frac34' - 191, 'iquest' - 192, 'Agrave' - 193, 'Aacute' - 194, 'Acirc' - 195, 'Atilde' - 196, 'Auml' - 197, 'Aring' - 198, 'AElig' - 199, 'Ccedil' - 200, 'Egrave' - 201, 'Eacute' - 202, 'Ecirc' - 203, 'Euml' - 204, 'Igrave' - 205, 'Iacute' - 206, 'Icirc' - 207, 'Iuml' - 208, 'ETH' - 209, 'Ntilde' - 210, 'Ograve' - 211, 'Oacute' - 212, 'Ocirc' - 213, 'Otilde' - 214, 'Ouml' - 215, 'times' - 216, 'Oslash' - 217, 'Ugrave' - 218, 'Uacute' - 219, 'Ucirc' - 220, 'Uuml' - 221, 'Yacute' - 222, 'THORN' - 223, 'szlig' - 224, 'agrave' - 225, 'aacute' - 226, 'acirc' - 227, 'atilde' - 228, 'auml' - 229, 'aring' - 230, 'aelig' - 231, 'ccedil' - 232, 'egrave' - 233, 'eacute' - 234, 'ecirc' - 235, 'euml' - 236, 'igrave' - 237, 'iacute' - 238, 'icirc' - 239, 'iuml' - 240, 'eth' - 241, 'ntilde' - 242, 'ograve' - 243, 'oacute' - 244, 'ocirc' - 245, 'otilde' - 246, 'ouml' - 247, 'divide' - 248, 'oslash' - 249, 'ugrave' - 250, 'uacute' - 251, 'ucirc' - 252, 'uuml' - 253, 'yacute' - 254, 'thorn' - ", sep = ",", header = T, quote = "'", strip.white = T) -htmlcodes$char <- intToUtf8(htmlcodes$char, T) -htmlcodes$code <- paste0("&", htmlcodes$code, ";") - -htmlcodes <- rbind(htmlcodes, data.frame( - char = intToUtf8(32:383, T), - code = sprintf("&#%03i;", 32:383) -)) - -# An oversimplistic function to unescape html escape codes -.htmlUnescape <- function(text) { - for (i in 1:nrow(htmlcodes)) - text <- gsub(htmlcodes$code[i], htmlcodes$char[i], text, fixed = T) - Encoding(text) <- "UTF-8" - return(text) -} - -#' ModArchive helper functions -#' -#' is on of the largest online archive of module files. These functions -#' will assist in accessing this archive. -#' -#' The `modArchive.info` function will retrieve info on a specific module from the -#' ModArchive. The `modArchive.search.mod`, `modArchive.search.genre` and -#' `modArchive.search.hash` functions can be used to find specific modules -#' in the archive. Use `modArchive.random.pick` to get module info on a random -#' module in the archive. -#' -#' Use the `modArchive.view.by` -#' function to browse the archive by specific aspects. -#' Note that the ModArchive also contains file formats other than ProTracker's MOD format. -#' This package can only handle the MOD format. -#' -#' The `modArchive.download` function will download a module from the archive. -#' -#' Use `modArchive.search.artist` to find artist details in the archive. -#' -#' Use `modArchive.request.count` to determine how many request you have -#' made in the current month with the specified key (see `ModArchive API key' -#' section for details). -#' Use `modArchive.max.requests` to determine how many request you are -#' allowed to make each month with the provided key (see `ModArchive API key' -#' section for details). -#' -#' @section ModArchive API key: -#' Since ProTrackR 0.3.4, the ModArchive helper functions have changed. In earlier -#' version, a labile html scraper was used, in 0.3.4 and later, this is replaced by -#' functions that more robustly use the Application Programming Interface (API) -#' provided by ModArchive. There are some downsides to this new approach: a -#' personal API key needs to be obtained from the ModArchive team; and the -#' ProTrackR package relies on yet another package (XML) -#' to parse the XML files that are returned by the API. -#' -#' So why is this switch? Well, first of all, this approach is better supported -#' by ModArchive. The personal API key is used to avoid excessive access by imposing -#' a monthly request limit (keep in mind that ModArchive provides free services and is -#' run by volunteers). The upside is that the XML files are a lot lighter than the -#' html files returned by the regular website. Therefore, the new functions are faster, -#' and they reduce the load on the ModArchive servers. The XML files also allow for -#' easier access to more of the ModArchive functionality as implemented in the -#' ModArchive helper functions described here. -#' -#' So how do you get your personal API key? First, you need to register at the -#' [ModArchive Forums](https://modarchive.org/forums/). Then follow the -#' instructions provided in this [topic](https://modarchive.org/forums/index.php?topic=1950.0) -#' on the forum. For more info, see also the [API page](https://modarchive.org/?xml-api) -#' on ModArchive. -#' -#' If you want to search for module files without an API key, one could make use of -#' to the [modLand] collection instead. -#' @param mod.id An `integer` code used as module identifier in the ModArchive database. -#' A `mod.id` can be obtained by performing a search with `modArchive.search.mod`. -#' When downloading a module, make sure that the identifier represents a MOD file, as -#' other types will result in an error. -#' @param search.text A `character` string to be used as terms to search -#' in the ModArchive. -#' @param search.where A `character` string indicating where in the module files -#' to search for the `search.text`. See usage section for the available options. -#' @param format.filter File format filter to be used in a search in the ModArchive. -#' See the usage section for all possible options. Default is "unset" (meaning that -#' it will search for any file format). Note that only the `MOD' format -#' is supported by this package. -#' @param size.filter File size filter to be used in a search in the ModArchive. -#' Needs to be a `character` string representation of a file size -#' category as specified on ModArchive.org. -#' See the usage section for all possible options. Default is "unset" (meaning that -#' it will search for any file size). Note that the maximum file size of a -#' module is approximately 4068 kilobytes, meaning that the largest file size -#' category is irrelevant for `MOD' files. Also note that the category names are -#' inconsistant, these are the literal catagories used by ModArchive -#' @param genre.filter Genre filter to be used in some of the overviews from the ModArchive. -#' Needs to be a `character` string representation of a genre -#' as specified on ModArchive.org. -#' See the usage section for all possible options. -#' This argument is deprecated in the function `modArchive.search` since ProTrackR -#' version 0.3.4, other functions will still accept this argument. -#' @param search.artist A character string representing the (guessed) artist name -#' or id number that you ar looking for in the archive. -#' @param search.hash The MD5 hash code of the specific module you are looking -#' for. See for details. -#' @param view.query A query to be used in combination with the `view.by` -#' argument. Use the queries in combination with `view.by` as follows: -#' * `view_by_list`: Use a single capital starting letter to browse -#' modules by name -#' * `view_by_rating_comments`: Provide a (user) rating by which you -#' wish to browse the modules -#' * `view_by_rating_reviews`: Provide a (reviewer) rating by which you -#' wish to browse the modules -#' * `view_modules_by_artistid`: Provide an artist id number -#' for whom you wish to browse his/her modules -#' * `view_modules_by_guessed_artist`: Provide an artist guessed -#' name for whom you wish to browser his/her modules -#' @param api.key Most ModArchive functions require a personal secret API key. This key can -#' be obtained from the ModArchive forum. See `ModArchive API Key' section below for instructions -#' on how to obtain such a key. -#' @param page Many of the ModArchive returns paginated tables. When this argument -#' is omitted, the first page is returned. Use an integer value to return a specific -#' page. The total number of pages of a search or view is returned as an attribute -#' to the returned [base::data.frame]. -#' @param view.by Indicate how the `modArchive.view.by` function should sort -#' the overview tables of modules. See `usage' section for the possible options. -#' @param ... arguments that are passed on to [`read.module`]. -#' @returns `modArchive.info`, `modArchive.search.genre`, -#' `modArchive.search.hash`, `modArchive.random.pick` and -#' `modArchive.view.by` will return a [data.frame] -#' containing information on modules in the ModArchive. Note that this -#' data.frame is formatted differently since ProTrackR 0.3.4, which -#' may cause backward compatibility issues. -#' -#' `modArchive.download` will download a module and return it as a -#' [`PTModule`] object. -#' -#' `modArchive.search.artist` will return a [`data.frame`] -#' containing information on artists on the ModArchive. -#' -#' `modArchive.request.count` returns the number of ModArchive API request -#' that are left for this month, for the provided key. -#' -#' `modArchive.max.requests` returns the maximum monthly requests for the -#' provided key. -#' @name modArchive -#' @aliases modArchive.info -#' @aliases modArchive.download -#' @aliases modArchive.search.mod -#' @aliases modArchive.search.genre -#' @aliases modArchive.search.hash -#' @aliases modArchive.search.artist -#' @aliases modArchive.random.pick -#' @aliases modArchive.view.by -#' @aliases modArchive.request.count -#' @aliases modArchive.max.requests -#' @rdname modArchive -#' @examples -#' \dontrun{ -#' ## most of the example below will fail as they require a -#' ## real modArchive API key. The key used in these example -#' ## is just a dummy. See details on how to get a key -#' ## in the section 'ModArchive API Key' in the manual. -#' -#' ## Search for the module that is also used as -#' ## an example in this package: -#' search.results <- modArchive.search.mod("*_-_intro.mod", -#' size.filter = "0-99", -#' format.filter = "MOD", -#' api.key = "") -#' -#' ## apparently there are multiple modules in -#' ## database that have '_-_intro' in their -#' ## file name or title. Select the wanted -#' ## module from the list (the one with the -#' ## word 'protrackr' in the instrument names): -#' search.select <- subset(search.results, -#' grepl("protrackr", search.results$instruments)) -#' -#' ## get the same details, but now only for -#' ## the specific module based on its ModArchive ID: -#' modArchive.info(search.select$id, api.key = "") -#' -#' ## download the selected module from ModArchive.org: -#' mod <- modArchive.download(search.select$id) -#' -#' ## here's a randomly picked module from the ModArchive: -#' info.random <- modArchive.random.pick(api.key = "") -#' -#' ## use modArchive.view.by to list the 2nd page -#' ## of MOD files that start with the letter 'A' -#' info.list <- modArchive.view.by("A", "view_by_list", "MOD", -#' page = 2, -#' api.key = "") -#' -#' ## list the modules of the artist with id number 89200: -#' artist.mods <- modArchive.view.by("89200", "view_modules_by_artistid", -#' format.filter = "MOD", -#' api.key = "") -#' -#' ## here's how you can list MOD files of a -#' ## specific genre: -#' list.genre <- modArchive.search.genre("Chiptune", "MOD", -#' api.key = "") -#' -#' ## get module info for a specific hash code -#' mod.hash <- modArchive.search.hash("8f80bcab909f700619025bd7f2975749", -#' "") -#' -#' ## find modarchive artist info, search for artist name -#' ## or artist id: -#' artist.list <- modArchive.search.artist("89200", -#' api.key = "") -#' -#' ## How many requests did I make this month?: -#' modArchive.request.count("") -#' -#' ## How many requests am I allowed to make each month?: -#' modArchive.max.requests("") -#' } -#' @author Pepijn de Vries -#' @export -modArchive.info <- function(mod.id, api.key) -{ - mod.id <- as.integer(mod.id[[1]]) - api.key <- as.character(api.key[[1]]) - request.mod <- paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, "&request=view_by_moduleid&query=",mod.id) - result <- .get.module.table(request.mod, "module") - return(result) -} - -.get.module.table <- function(xmlcode, what) { - xmlcode <- XML::xmlParse(xmlcode, options = XML::NOCDATA) - result <- XML::xmlToList(xmlcode) - if (any("error" %in% names(result))) stop (as.character(result$error)) - totalpages <- as.numeric(result$totalpages) - results <- as.numeric(result$results) - - if (what == "item") result <- result$items - result <- lapply(result[names(result) == what], function(x) { - lapply(x, function(x) { - if (length(x) > 1) { - x <- lapply(x, function(x) { - x[is.null(x)] <- "NULL" - x - }) - x <- unlist(x) - paste(apply(cbind(names(x), paste0("<", x, ">")), 1, paste, - collapse = "="), collapse = ";") - } else - { - x[is.null(x)] <- "" - x - } - }) - }) - - result <- lapply(result, function(x) { - x <- lapply(x, function(x) if (length(x) == 0) return("") else return(x)) - data.frame(t(unlist(x))) - }) - result <- do.call(rbind, result) - row.names(result) <- NULL - if (what == "module") result <- .fix.module.table(result) - if (what == "item") result <- .fix.artist.table(result) - attr(result, "results") <- results - attr(result, "totalpages") <- totalpages - return(result) -} - -.fix.module.table <- function(result) { - result <- as.data.frame(as.matrix(result), stringsAsFactors = F) - result$songtitle <- .htmlUnescape(result$songtitle) - result$instruments <- .htmlUnescape(result$instruments) - result$comment <- .htmlUnescape(result$comment) - result$timestamp <- as.POSIXct(as.numeric(result$timestamp), - origin = "1970-01-01 00:00", tz = "CET") - numeric_sel <- c("bytes", "hits", "genreid", "id", "channels") - result[,numeric_sel] <- as.data.frame(lapply(result[,numeric_sel], as.numeric)) - - return(result) -} - -.fix.artist.table <- function(result) { - result <- as.data.frame(as.matrix(result), stringsAsFactors = F) - result$timestamp <- as.POSIXct(as.numeric(result$timestamp), - origin = "1970-01-01 00:00", tz = "CET") - numeric_sel <- c("id", "isartist") - result[,numeric_sel] <- as.data.frame(lapply(result[,numeric_sel], as.numeric)) - - return(result) -} - -#' @rdname modArchive -#' @export -modArchive.download <- function(mod.id, ...) -{ - mod.id <- as.integer(mod.id[[1]]) - con <- url(paste("https://api.modarchive.org/downloads.php?moduleid=", mod.id, sep = ""), "rb") - mod <- read.module(con, ...) - close(con) - return (mod) -} - -#' @rdname modArchive -#' @export -modArchive.search.mod <- function(search.text, - search.where = c("filename_or_songtitle", "filename_and_songtitle", "filename", "songtitle", "module_instruments", "module_comments"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", "3072-6999", "7168-100000"), - genre.filter = "deprecated", - page, - api.key) -{ - search.text <- utils::URLencode(as.character(search.text[[1]])) - search.where <- match.arg(search.where) - format.filter <- match.arg(format.filter) - size.filter <- match.arg(size.filter) - api.key <- as.character(api.key[[1]]) - if (!missing(genre.filter)) warning("Argument 'genre.filter' is deprecated in this function and not used since ProTrackR version 0.3.4. Use 'modArchive.view.by' to browse modules by genre.") - - xmlcode <- paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, - "&request=search&query=", - search.text, - "&type=", - search.where) - if (format.filter != "unset") xmlcode <- paste0(xmlcode, "&format=", format.filter) - if (genre.filter != "unset") xmlcode <- paste0(xmlcode, "&genreid=", genre.filter) - if (size.filter != "unset") xmlcode <- paste0(xmlcode, "&size=", size.filter) - if (!missing(page)) xmlcode <- paste0(xmlcode, "&page=", as.integer(page[[1]])) - result <- .get.module.table(xmlcode, "module") - return(result) -} - -#' @rdname modArchive -#' @export -modArchive.request.count <- function(api.key) { - return(.requests("current", api.key)) -} - -#' @rdname modArchive -#' @export -modArchive.max.requests <- function(api.key) { - return(.requests("maximum", api.key)) -} - -.requests <- function(index, api.key) -{ - request.count <- XML::xmlTreeParse(paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, - "&request=view_requests")) - count.root <- XML::xmlRoot(request.count) - count.values <- XML::xmlSApply(count.root, function(x) XML::xmlSApply(x, XML::xmlValue)) - return(as.integer(count.values$requests[[index]])) -} - -#' @rdname modArchive -#' @export -modArchive.view.by <- function(view.query, - view.by = c("view_by_list", - "view_by_rating_comments", - "view_by_rating_reviews", - "view_modules_by_artistid", - "view_modules_by_guessed_artist"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", "3072-6999", "7168-100000"), - page, - api.key) { - view.query <- as.character(view.query[[1]]) - format.filter <- match.arg(format.filter) - size.filter <- match.arg(size.filter) - api.key <- as.character(api.key[[1]]) - - xmlcode <- paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, - "&request=", view.by, - "&query=", - view.query) - if (format.filter != "unset") xmlcode <- paste0(xmlcode, "&format=", format.filter) - if (size.filter != "unset") xmlcode <- paste0(xmlcode, "&size=", size.filter) - if (!missing(page)) xmlcode <- paste0(xmlcode, "&page=", as.integer(page[[1]])) - result <- .get.module.table(xmlcode, "module") - return(result) -} - -#' @rdname modArchive -#' @export -modArchive.search.genre <- function(genre.filter = c("unset", "Alternative", "Gothic", "Grunge", "Metal - Extreme", "Metal (general)", "Punk", "Chiptune", "Demo Style", - "One Hour Compo", "Chillout", "Electronic - Ambient", "Electronic - Breakbeat", "Electronic - Dance", - "Electronic - Drum and Bass", "Electronic - Gabber", "Electronic - Hardcore", "Electronic - House", "Electronic - IDM", - "Electronic - Industrial", "Electronic - Jungle", "Electronic - Minimal", "Electronic - Other", - "Electronic - Progressive", "Electronic - Rave", "Electronic - Techno", "Electronic (general)", "Trance - Acid", - "Trance - Dream", "Trance - Goa", "Trance - Hard", "Trance - Progressive", "Trance - Tribal", "Trance (general)", - "Big Band", "Blues", "Jazz - Acid", "Jazz - Modern", "Jazz (general)", "Swing", "Bluegrass", "Classical", "Comedy", - "Country", "Experimental", "Fantasy", "Folk", "Fusion", "Medieval", "New Ages", "Orchestral", "Other", "Piano", - "Religious", "Soundtrack", "Spiritual", "Video Game", "Vocal Montage", "World", "Ballad", "Disco", "Easy Listening", - "Funk", "Pop - Soft", "Pop - Synth", "Pop (general)", "Rock - Hard", "Rock - Soft", "Rock (general)", "Christmas", - "Halloween", "Hip-Hop", "R and B", "Reggae", "Ska", "Soul"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", "3072-6999", "7168-100000"), - page, - api.key) { - genre.filter <- match.arg(genre.filter) - genre.filter <- genre.table$genre.id[genre.table$genre == genre.filter] - format.filter <- match.arg(format.filter) - size.filter <- match.arg(size.filter) - api.key <- as.character(api.key[[1]]) - - xmlcode <- paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, - "&request=search&type=genre&query=", - genre.filter) - if (format.filter != "unset") xmlcode <- paste0(xmlcode, "&format=", format.filter) - if (size.filter != "unset") xmlcode <- paste0(xmlcode, "&size=", size.filter) - if (!missing(page)) xmlcode <- paste0(xmlcode, "&page=", as.integer(page[[1]])) - result <- .get.module.table(xmlcode, "module") - return(result) -} - -#' @rdname modArchive -#' @export -modArchive.search.artist <- function(search.artist, page, api.key) { - api.key <- as.character(api.key[[1]]) - search.artist <- as.character(search.artist[[1]]) - api.key <- as.character(api.key[[1]]) - xmlcode <- paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, - "&request=search_artist&query=", - search.artist) - if (!missing(page)) xmlcode <- paste0(xmlcode, "&page=", as.integer(page[[1]])) - result <- .get.module.table(xmlcode, "item") - return(result) -} - -#' @rdname modArchive -#' @export -modArchive.search.hash <- function(search.hash, api.key) { - search.hash <- as.character(search.hash[[1]]) - api.key <- as.character(api.key[[1]]) - xmlcode <- paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, - "&request=search&type=hash&query=", - search.hash) - result <- .get.module.table(xmlcode, "module") - return(result) -} - -#' @rdname modArchive -#' @export -modArchive.random.pick <- function(genre.filter = c("Alternative", "Gothic", "Grunge", "Metal - Extreme", "Metal (general)", "Punk", "Chiptune", "Demo Style", - "One Hour Compo", "Chillout", "Electronic - Ambient", "Electronic - Breakbeat", "Electronic - Dance", - "Electronic - Drum and Bass", "Electronic - Gabber", "Electronic - Hardcore", "Electronic - House", "Electronic - IDM", - "Electronic - Industrial", "Electronic - Jungle", "Electronic - Minimal", "Electronic - Other", - "Electronic - Progressive", "Electronic - Rave", "Electronic - Techno", "Electronic (general)", "Trance - Acid", - "Trance - Dream", "Trance - Goa", "Trance - Hard", "Trance - Progressive", "Trance - Tribal", "Trance (general)", - "Big Band", "Blues", "Jazz - Acid", "Jazz - Modern", "Jazz (general)", "Swing", "Bluegrass", "Classical", "Comedy", - "Country", "Experimental", "Fantasy", "Folk", "Fusion", "Medieval", "New Ages", "Orchestral", "Other", "Piano", - "Religious", "Soundtrack", "Spiritual", "Video Game", "Vocal Montage", "World", "Ballad", "Disco", "Easy Listening", - "Funk", "Pop - Soft", "Pop - Synth", "Pop (general)", "Rock - Hard", "Rock - Soft", "Rock (general)", "Christmas", - "Halloween", "Hip-Hop", "R and B", "Reggae", "Ska", "Soul"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", "3072-6999", "7168-100000"), - api.key) { - genre.filter <- match.arg(genre.filter) - genre.filter <- genre.table$genre.id[genre.table$genre == genre.filter] - format.filter <- match.arg(format.filter) - size.filter <- match.arg(size.filter) - api.key <- as.character(api.key[[1]]) - - xmlcode <- paste0("https://api.modarchive.org/xml-tools.php?key=", - api.key, "&request=random") - if (format.filter != "unset") xmlcode <- paste0(xmlcode, "&format=", format.filter) - if (size.filter != "unset") xmlcode <- paste0(xmlcode, "&size=", size.filter) - if (genre.filter != "unset") xmlcode <- paste0(xmlcode, "&genreid=", genre.filter) - result <- .get.module.table(xmlcode, "module") - return(result) -} diff --git a/R/12ModLandHelpers.r b/R/12ModLandHelpers.r deleted file mode 100644 index 5541ba6..0000000 --- a/R/12ModLandHelpers.r +++ /dev/null @@ -1,129 +0,0 @@ -#' ModLand helper functions -#' -#' is on of the largest online archive of module files. These functions -#' will assist in accessing this archive. -#' -#' Like the , modland provides access to a large collection of module files. -#' Compared to the [modArchive], modLand provides limited searching features. However, it -#' does not require an API key. -#' -#' The functions documented here are provided as a convenience and depend -#' on third party services. Note that continuity of these services cannot -#' be guaranteed. -#' -#' Use `modLand.search.mod` to search through the modLand collection. -#' -#' Use `modLand.download.mod` to download a specific mod file as an S4 object. -#' @param search.text A single length `character` vector, containing -#' search text. Provided search pattern is searched in all fields (mod format, -#' author and title). Prefixes can be added to keywords for inclusive or exclusive -#' searches. For details see . -#' Note that modLand contains a wide range of tracker files, only mod-files -#' are supported by the `ProTrackR` package. It is therefore advisable to add the -#' keyword `mod' to the search string. -#' @param format A single length `character` vector, indicating the -#' tracker file format. ``Protracker`' is the option that is most likely to work in this package. -#' @param author A single length `character` vector, indicating the -#' module author name. Can be obtained from a `modLand.search.mod`. -#' @param title A single length `character` vector, indicating the -#' module title. Can be obtained from a `modLand.search.mod`. -#' @param mirror A single length `character` vector. Should contain one of the -#' mirrors listed in the `usage' section. Select a mirror site from which -#' the module file needs to be downloaded. -#' @param ... Argument that are passed on to [`read.module`]. -#' @returns `modLand.search.mod` returns a `data.frame`. -#' The `data.frame` contains a search result in each row. -#' The data.frame contains a number of columns, each containing -#' `character` strings. The column `title' contains the mod file name; -#' The column named `author' contains the author name; the column named -#' `format' contains the tracker file format (only ``Protracker`' -#' is supported by this package); The collumn `collect' contains -#' modLand collections in which the mod is included; the column named -#' `url' contains a download link for the `ogg'-file generated on the -#' modLand server from the mod file. Note that ogg-files are not supported -#' by the ProTrackR package. Use `modLand.download.mod` to download -#' the mod file. -#' -#' `modLand.download.mod` attempts to download the specified mod -#' file and return it as a [`PTModule`] object. It will throw -#' errors when the mod file is not available or when there are network -#' problems... -#' @name modLand -#' @aliases modLand.search.mod -#' @aliases modLand.download.mod -#' @rdname modLand -#' @examples -#' \dontrun{ -#' ## Search for a funky tune: -#' -#' modland <- modLand.search.mod("elekfunk mod") -#' -#' ## The ogg file can be downloaded (in this case to the tempdir()), -#' ## but it is not supported by the ProTrackR package... -#' -#' utils::download.file(modland$url[1], tempdir()) -#' -#' ## Instead, use the following approach to download the module: -#' -#' mod <- modLand.download.mod(modland$format[1], -#' modland$author[1], -#' modland$title[1]) -#' -#' } -#' @author Pepijn de Vries -#' @export -modLand.search.mod <- function(search.text) { - con <- url(paste0("https://www.exotica.org.uk/mediawiki/extensions/ExoticASearch/Modland_xbmc.php?qs=", - utils::URLencode(search.text))) - modland <- readLines(con) - close(con) - ## when there are no results, the length of the file is 2 lines long - if (length(modland) <= 2) { - return(data.frame( - title = character(0), - author = character(0), - format = character(0), - collect = character(0), - url = character(0), - stringsAsFactors = F - )) - } - modland <- XML::xmlTreeParse(modland) - modland <- XML::xmlApply(modland, XML::xmlToList) - modland <- lapply(modland, rbind) - modland <- as.data.frame(do.call(rbind, modland)) - modland <- lapply(modland, unlist) - modland <- as.data.frame(do.call(cbind, modland), - stringsAsFactors = F) - modland -} - -#' @rdname modLand -#' @export -modLand.download.mod <- function(format, - author, - title, - mirror = c("modland.com", - "ftp.modland.com", - "antarctica.no", - "ziphoid.com", - "exotica.org.uk"), - ...) { - mirror.args <- c("modland.com", - "ftp.modland.com", - "antarctica.no", - "ziphoid.com", - "exotica.org.uk") - mirror <- match(match.arg(mirror, mirror.args), mirror.args) - mirror <- c("https://modland.com/pub/modules/", - "ftp://ftp.modland.com/pub/modules/", - "https://modland.antarctica.no/pub/modules/", - "https://modland.ziphoid.com/pub/modules/", - "https://files.exotica.org.uk/modland/?file=pub/modules/")[mirror] - url.suffix <- paste(utils::URLencode(format), - utils::URLencode(author), - utils::URLencode(title), - sep = "/") - download.url <- paste0(mirror, url.suffix) - read.module(download.url, ...) -} diff --git a/R/deprecated.R b/R/deprecated.R new file mode 100644 index 0000000..b6fe9e7 --- /dev/null +++ b/R/deprecated.R @@ -0,0 +1,90 @@ +#' Deprecated function migrated to `openmpt` +#' +#' Functions listed on this page are deprecated and have migrated to the +#' [openmpt](https://pepijn-devries.github.io/openmpt/articles/modarchive.html) package. +#' @param ... Ignored +#' @returns Returns `NULL`. +#' @rdname deprecated +#' @export +modArchive.info <- function(...) { + .Deprecated("modarchive_info", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.download <- function(...) { + .Deprecated("modarchive_download", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.search.mod <- function(...) { + .Deprecated("modarchive_search_mod", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.request.count <- function(...) { + .Deprecated("modarchive_requests", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.max.requests <- function(...) { + .Deprecated("modarchive_requests", package = "openmpt") + NULL +} + + +#' @rdname deprecated +#' @export +modArchive.view.by <- function(...) { + .Deprecated("modarchive_view_by", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.search.genre <- function(...) { + .Deprecated("modarchive_search_genre", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.search.artist <- function(...) { + .Deprecated("modarchive_search_artist", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.search.hash <- function(...) { + .Deprecated("modarchive_search_hash", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modArchive.random.pick <- function(...) { + .Deprecated("modarchive_random", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modLand.search.mod <- function(...) { + .Deprecated("modland_search", package = "openmpt") + NULL +} + +#' @rdname deprecated +#' @export +modLand.download.mod <- function(...) { + .Deprecated("modland_download", package = "openmpt") + NULL +} diff --git a/README.Rmd b/README.Rmd index 95d2c78..129eb6c 100644 --- a/README.Rmd +++ b/README.Rmd @@ -16,6 +16,13 @@ data("mod.intro") # ProTrackR + +[![R-CMD-check](https://github.com/pepijn-devries/ProTrackR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/pepijn-devries/ProTrackR/actions/workflows/R-CMD-check.yaml) +[![ProTrackR2 status badge](https://pepijn-devries.r-universe.dev/badges/ProTrackR)](https://pepijn-devries.r-universe.dev/ProTrackR) +[![version](https://www.r-pkg.org/badges/version/ProTrackR)](https://CRAN.R-project.org/package=ProTrackR) +![cranlogs](https://cranlogs.r-pkg.org/badges/ProTrackR) + + ProTracker 2.3a [ProTracker](https://en.wikipedia.org/wiki/Protracker) is music sequencer software diff --git a/README.md b/README.md index b65c1dc..fd84947 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ # ProTrackR + + +[![R-CMD-check](https://github.com/pepijn-devries/ProTrackR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/pepijn-devries/ProTrackR/actions/workflows/R-CMD-check.yaml) +[![ProTrackR2 status +badge](https://pepijn-devries.r-universe.dev/badges/ProTrackR)](https://pepijn-devries.r-universe.dev/ProTrackR) +[![version](https://www.r-pkg.org/badges/version/ProTrackR)](https://CRAN.R-project.org/package=ProTrackR) +![cranlogs](https://cranlogs.r-pkg.org/badges/ProTrackR) + + ProTracker 2.3a [ProTracker](https://en.wikipedia.org/wiki/Protracker) is music diff --git a/man/MODPlugToPTPattern.Rd b/man/MODPlugToPTPattern.Rd index 023a667..3b70fa5 100644 --- a/man/MODPlugToPTPattern.Rd +++ b/man/MODPlugToPTPattern.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/11MODPlugHelpers.r +% Please edit documentation in R/10MODPlugHelpers.r \name{MODPlugToPTPattern} \alias{MODPlugToPTPattern} \title{Convert MODPlug pattern into a PTPattern object} @@ -33,7 +33,6 @@ and use this function to import it to R as a \code{\link{PTPattern}} or \code{\link{PTBlock}} object. } \examples{ -\dontrun{ ## This is what Mod Plug Pattern data looks like on ## the system's clipboard: modPlugPattern <- c("ModPlug Tracker MOD", @@ -114,7 +113,6 @@ class(pat) ## PTBlock: blk <- MODPlugToPTPattern(modPlugPattern[1:10], "PTBlock") } -} \seealso{ Other MODPlug.operations: \code{\link{PTPatternToMODPlug}()} diff --git a/man/PTPatternToMODPlug.Rd b/man/PTPatternToMODPlug.Rd index a7b4193..20c456e 100644 --- a/man/PTPatternToMODPlug.Rd +++ b/man/PTPatternToMODPlug.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/11MODPlugHelpers.r +% Please edit documentation in R/10MODPlugHelpers.r \name{PTPatternToMODPlug} \alias{PTPatternToMODPlug} \title{Convert PTPattern data into a MODPlug pattern} \usage{ -PTPatternToMODPlug(x, to.clipboard = T) +PTPatternToMODPlug(x, to.clipboard = TRUE) } \arguments{ \item{x}{Either a \code{\link{PTPattern}} object or a @@ -32,7 +32,6 @@ music tracker that is for free. It too can handle ProTracker modules. This function assists in moving pattern data from R to Open MPT. } \examples{ -\dontrun{ ## get some pattern data pattern <- PTPattern(mod.intro, 1) @@ -47,14 +46,13 @@ PTPatternToMODPlug(pattern) ## If you want to handle the pattern data ## in R: -patModPlug <- PTPatternToMODPlug(pattern, F) +patModPlug <- PTPatternToMODPlug(pattern, FALSE) ## We can do the same with a block: block <- PTBlock(pattern, 1:10, 2:3) PTPatternToMODPlug(block) } -} \seealso{ Other MODPlug.operations: \code{\link{MODPlugToPTPattern}()} diff --git a/man/deprecated.Rd b/man/deprecated.Rd new file mode 100644 index 0000000..1befc53 --- /dev/null +++ b/man/deprecated.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated.R +\name{modArchive.info} +\alias{modArchive.info} +\alias{modArchive.download} +\alias{modArchive.search.mod} +\alias{modArchive.request.count} +\alias{modArchive.max.requests} +\alias{modArchive.view.by} +\alias{modArchive.search.genre} +\alias{modArchive.search.artist} +\alias{modArchive.search.hash} +\alias{modArchive.random.pick} +\alias{modLand.search.mod} +\alias{modLand.download.mod} +\title{Deprecated function migrated to \code{openmpt}} +\usage{ +modArchive.info(...) + +modArchive.download(...) + +modArchive.search.mod(...) + +modArchive.request.count(...) + +modArchive.max.requests(...) + +modArchive.view.by(...) + +modArchive.search.genre(...) + +modArchive.search.artist(...) + +modArchive.search.hash(...) + +modArchive.random.pick(...) + +modLand.search.mod(...) + +modLand.download.mod(...) +} +\arguments{ +\item{...}{Ignored} +} +\value{ +Returns \code{NULL}. +} +\description{ +Functions listed on this page are deprecated and have migrated to the +\href{https://pepijn-devries.github.io/openmpt/articles/modarchive.html}{openmpt} package. +} diff --git a/man/fix.PTModule.Rd b/man/fix.PTModule.Rd index 51de2ed..b19346d 100644 --- a/man/fix.PTModule.Rd +++ b/man/fix.PTModule.Rd @@ -6,7 +6,7 @@ \alias{fix.PTModule,PTModule,missing-method} \title{Attempt to fix PTModule to ProTracker specs} \usage{ -\S4method{fix.PTModule}{PTModule,logical}(mod, verbose = T) +\S4method{fix.PTModule}{PTModule,logical}(mod, verbose = TRUE) \S4method{fix.PTModule}{PTModule,missing}(mod) } @@ -42,7 +42,6 @@ In the current version, pattern data itself is not checked for non-conformaties nor is it fixed. } \examples{ -\dontrun{ data("mod.intro") ## Let's do something illegal and destroy mod.intro: @@ -57,8 +56,7 @@ validObject(mod.intro, TRUE) mod.intro <- fix.PTModule(mod.intro) ## See, it's all OK again: -validObject(mod.intro, TRUE) -} +validObject(mod.intro, FALSE) } \seealso{ Other module.operations: diff --git a/man/modArchive.Rd b/man/modArchive.Rd deleted file mode 100644 index d185b5c..0000000 --- a/man/modArchive.Rd +++ /dev/null @@ -1,314 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/10ModArchiveHelpers.r -\name{modArchive} -\alias{modArchive} -\alias{modArchive.info} -\alias{modArchive.download} -\alias{modArchive.search.mod} -\alias{modArchive.search.genre} -\alias{modArchive.search.hash} -\alias{modArchive.search.artist} -\alias{modArchive.random.pick} -\alias{modArchive.view.by} -\alias{modArchive.request.count} -\alias{modArchive.max.requests} -\title{ModArchive helper functions} -\usage{ -modArchive.info(mod.id, api.key) - -modArchive.download(mod.id, ...) - -modArchive.search.mod( - search.text, - search.where = c("filename_or_songtitle", "filename_and_songtitle", "filename", - "songtitle", "module_instruments", "module_comments"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", - "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", - "3072-6999", "7168-100000"), - genre.filter = "deprecated", - page, - api.key -) - -modArchive.request.count(api.key) - -modArchive.max.requests(api.key) - -modArchive.view.by( - view.query, - view.by = c("view_by_list", "view_by_rating_comments", "view_by_rating_reviews", - "view_modules_by_artistid", "view_modules_by_guessed_artist"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", - "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", - "3072-6999", "7168-100000"), - page, - api.key -) - -modArchive.search.genre( - genre.filter = c("unset", "Alternative", "Gothic", "Grunge", "Metal - Extreme", - "Metal (general)", "Punk", "Chiptune", "Demo Style", "One Hour Compo", "Chillout", - "Electronic - Ambient", "Electronic - Breakbeat", "Electronic - Dance", - "Electronic - Drum and Bass", "Electronic - Gabber", "Electronic - Hardcore", - "Electronic - House", "Electronic - IDM", "Electronic - Industrial", - "Electronic - Jungle", "Electronic - Minimal", "Electronic - Other", - "Electronic - Progressive", "Electronic - Rave", "Electronic - Techno", - - "Electronic (general)", "Trance - Acid", "Trance - Dream", "Trance - Goa", - "Trance - Hard", "Trance - Progressive", "Trance - Tribal", "Trance (general)", - "Big Band", "Blues", "Jazz - Acid", "Jazz - Modern", "Jazz (general)", "Swing", - "Bluegrass", "Classical", "Comedy", "Country", "Experimental", "Fantasy", "Folk", - "Fusion", "Medieval", "New Ages", "Orchestral", "Other", "Piano", "Religious", - "Soundtrack", "Spiritual", "Video Game", "Vocal Montage", "World", "Ballad", "Disco", - "Easy Listening", - "Funk", "Pop - Soft", "Pop - Synth", "Pop (general)", - "Rock - Hard", "Rock - Soft", "Rock (general)", "Christmas", "Halloween", "Hip-Hop", - "R and B", "Reggae", "Ska", "Soul"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", - "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", - "3072-6999", "7168-100000"), - page, - api.key -) - -modArchive.search.artist(search.artist, page, api.key) - -modArchive.search.hash(search.hash, api.key) - -modArchive.random.pick( - genre.filter = c("Alternative", "Gothic", "Grunge", "Metal - Extreme", - "Metal (general)", "Punk", "Chiptune", "Demo Style", "One Hour Compo", "Chillout", - "Electronic - Ambient", "Electronic - Breakbeat", "Electronic - Dance", - "Electronic - Drum and Bass", "Electronic - Gabber", "Electronic - Hardcore", - "Electronic - House", "Electronic - IDM", "Electronic - Industrial", - "Electronic - Jungle", "Electronic - Minimal", "Electronic - Other", - "Electronic - Progressive", "Electronic - Rave", "Electronic - Techno", - "Electronic (general)", - "Trance - Acid", "Trance - Dream", "Trance - Goa", - "Trance - Hard", "Trance - Progressive", "Trance - Tribal", "Trance (general)", - "Big Band", "Blues", "Jazz - Acid", "Jazz - Modern", "Jazz (general)", "Swing", - "Bluegrass", "Classical", "Comedy", "Country", "Experimental", "Fantasy", "Folk", - "Fusion", "Medieval", "New Ages", "Orchestral", "Other", "Piano", "Religious", - "Soundtrack", "Spiritual", "Video Game", "Vocal Montage", "World", "Ballad", "Disco", - "Easy Listening", "Funk", "Pop - Soft", - "Pop - Synth", "Pop (general)", - "Rock - Hard", "Rock - Soft", "Rock (general)", "Christmas", "Halloween", "Hip-Hop", - "R and B", "Reggae", "Ska", "Soul"), - format.filter = c("unset", "669", "AHX", "DMF", "HVL", "IT", "MED", "MO3", "MOD", - "MTM", "OCT", "OKT", "S3M", "STM", "XM"), - size.filter = c("unset", "0-99", "100-299", "300-599", "600-1025", "1025-2999", - "3072-6999", "7168-100000"), - api.key -) -} -\arguments{ -\item{mod.id}{An \code{integer} code used as module identifier in the ModArchive database. -A \code{mod.id} can be obtained by performing a search with \code{modArchive.search.mod}. -When downloading a module, make sure that the identifier represents a MOD file, as -other types will result in an error.} - -\item{api.key}{Most ModArchive functions require a personal secret API key. This key can -be obtained from the ModArchive forum. See `ModArchive API Key' section below for instructions -on how to obtain such a key.} - -\item{...}{arguments that are passed on to \code{\link{read.module}}.} - -\item{search.text}{A \code{character} string to be used as terms to search -in the ModArchive.} - -\item{search.where}{A \code{character} string indicating where in the module files -to search for the \code{search.text}. See usage section for the available options.} - -\item{format.filter}{File format filter to be used in a search in the ModArchive. -See the usage section for all possible options. Default is "unset" (meaning that -it will search for any file format). Note that only the `MOD' format -is supported by this package.} - -\item{size.filter}{File size filter to be used in a search in the ModArchive. -Needs to be a \code{character} string representation of a file size -category as specified on ModArchive.org. -See the usage section for all possible options. Default is "unset" (meaning that -it will search for any file size). Note that the maximum file size of a -module is approximately 4068 kilobytes, meaning that the largest file size -category is irrelevant for `MOD' files. Also note that the category names are -inconsistant, these are the literal catagories used by ModArchive} - -\item{genre.filter}{Genre filter to be used in some of the overviews from the ModArchive. -Needs to be a \code{character} string representation of a genre -as specified on ModArchive.org. -See the usage section for all possible options. -This argument is deprecated in the function \code{modArchive.search} since ProTrackR -version 0.3.4, other functions will still accept this argument.} - -\item{page}{Many of the ModArchive returns paginated tables. When this argument -is omitted, the first page is returned. Use an integer value to return a specific -page. The total number of pages of a search or view is returned as an attribute -to the returned \link[base:data.frame]{base::data.frame}.} - -\item{view.query}{A query to be used in combination with the \code{view.by} -argument. Use the queries in combination with \code{view.by} as follows: -\itemize{ -\item \code{view_by_list}: Use a single capital starting letter to browse -modules by name -\item \code{view_by_rating_comments}: Provide a (user) rating by which you -wish to browse the modules -\item \code{view_by_rating_reviews}: Provide a (reviewer) rating by which you -wish to browse the modules -\item \code{view_modules_by_artistid}: Provide an artist id number -for whom you wish to browse his/her modules -\item \code{view_modules_by_guessed_artist}: Provide an artist guessed -name for whom you wish to browser his/her modules -}} - -\item{view.by}{Indicate how the \code{modArchive.view.by} function should sort -the overview tables of modules. See `usage' section for the possible options.} - -\item{search.artist}{A character string representing the (guessed) artist name -or id number that you ar looking for in the archive.} - -\item{search.hash}{The MD5 hash code of the specific module you are looking -for. See \url{https://modarchive.org/?xml-api-usage-level3} for details.} -} -\value{ -\code{modArchive.info}, \code{modArchive.search.genre}, -\code{modArchive.search.hash}, \code{modArchive.random.pick} and -\code{modArchive.view.by} will return a \link{data.frame} -containing information on modules in the ModArchive. Note that this -data.frame is formatted differently since ProTrackR 0.3.4, which -may cause backward compatibility issues. - -\code{modArchive.download} will download a module and return it as a -\code{\link{PTModule}} object. - -\code{modArchive.search.artist} will return a \code{\link{data.frame}} -containing information on artists on the ModArchive. - -\code{modArchive.request.count} returns the number of ModArchive API request -that are left for this month, for the provided key. - -\code{modArchive.max.requests} returns the maximum monthly requests for the -provided key. -} -\description{ -\url{https://ModArchive.org} is on of the largest online archive of module files. These functions -will assist in accessing this archive. -} -\details{ -The \code{modArchive.info} function will retrieve info on a specific module from the -ModArchive. The \code{modArchive.search.mod}, \code{modArchive.search.genre} and -\code{modArchive.search.hash} functions can be used to find specific modules -in the archive. Use \code{modArchive.random.pick} to get module info on a random -module in the archive. - -Use the \code{modArchive.view.by} -function to browse the archive by specific aspects. -Note that the ModArchive also contains file formats other than ProTracker's MOD format. -This package can only handle the MOD format. - -The \code{modArchive.download} function will download a module from the archive. - -Use \code{modArchive.search.artist} to find artist details in the archive. - -Use \code{modArchive.request.count} to determine how many request you have -made in the current month with the specified key (see \verb{ModArchive API key' section for details). Use }modArchive.max.requests\verb{to determine how many request you are allowed to make each month with the provided key (see}ModArchive API key' -section for details). -} -\section{ModArchive API key}{ - -Since ProTrackR 0.3.4, the ModArchive helper functions have changed. In earlier -version, a labile html scraper was used, in 0.3.4 and later, this is replaced by -functions that more robustly use the Application Programming Interface (API) -provided by ModArchive. There are some downsides to this new approach: a -personal API key needs to be obtained from the ModArchive team; and the -ProTrackR package relies on yet another package (XML) -to parse the XML files that are returned by the API. - -So why is this switch? Well, first of all, this approach is better supported -by ModArchive. The personal API key is used to avoid excessive access by imposing -a monthly request limit (keep in mind that ModArchive provides free services and is -run by volunteers). The upside is that the XML files are a lot lighter than the -html files returned by the regular website. Therefore, the new functions are faster, -and they reduce the load on the ModArchive servers. The XML files also allow for -easier access to more of the ModArchive functionality as implemented in the -ModArchive helper functions described here. - -So how do you get your personal API key? First, you need to register at the -\href{https://modarchive.org/forums/}{ModArchive Forums}. Then follow the -instructions provided in this \href{https://modarchive.org/forums/index.php?topic=1950.0}{topic} -on the forum. For more info, see also the \href{https://modarchive.org/?xml-api}{API page} -on ModArchive. - -If you want to search for module files without an API key, one could make use of -to the \link{modLand} collection instead. -} - -\examples{ -\dontrun{ -## most of the example below will fail as they require a -## real modArchive API key. The key used in these example -## is just a dummy. See details on how to get a key -## in the section 'ModArchive API Key' in the manual. - -## Search for the module that is also used as -## an example in this package: -search.results <- modArchive.search.mod("*_-_intro.mod", - size.filter = "0-99", - format.filter = "MOD", - api.key = "") - -## apparently there are multiple modules in -## database that have '_-_intro' in their -## file name or title. Select the wanted -## module from the list (the one with the -## word 'protrackr' in the instrument names): -search.select <- subset(search.results, - grepl("protrackr", search.results$instruments)) - -## get the same details, but now only for -## the specific module based on its ModArchive ID: -modArchive.info(search.select$id, api.key = "") - -## download the selected module from ModArchive.org: -mod <- modArchive.download(search.select$id) - -## here's a randomly picked module from the ModArchive: -info.random <- modArchive.random.pick(api.key = "") - -## use modArchive.view.by to list the 2nd page -## of MOD files that start with the letter 'A' -info.list <- modArchive.view.by("A", "view_by_list", "MOD", - page = 2, - api.key = "") - -## list the modules of the artist with id number 89200: -artist.mods <- modArchive.view.by("89200", "view_modules_by_artistid", - format.filter = "MOD", - api.key = "") - -## here's how you can list MOD files of a -## specific genre: -list.genre <- modArchive.search.genre("Chiptune", "MOD", - api.key = "") - -## get module info for a specific hash code -mod.hash <- modArchive.search.hash("8f80bcab909f700619025bd7f2975749", - "") - -## find modarchive artist info, search for artist name -## or artist id: -artist.list <- modArchive.search.artist("89200", - api.key = "") - -## How many requests did I make this month?: -modArchive.request.count("") - -## How many requests am I allowed to make each month?: -modArchive.max.requests("") -} -} -\author{ -Pepijn de Vries -} diff --git a/man/modLand.Rd b/man/modLand.Rd deleted file mode 100644 index 5d6fa8a..0000000 --- a/man/modLand.Rd +++ /dev/null @@ -1,96 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/12ModLandHelpers.r -\name{modLand} -\alias{modLand} -\alias{modLand.search.mod} -\alias{modLand.download.mod} -\title{ModLand helper functions} -\usage{ -modLand.search.mod(search.text) - -modLand.download.mod( - format, - author, - title, - mirror = c("modland.com", "ftp.modland.com", "antarctica.no", "ziphoid.com", - "exotica.org.uk"), - ... -) -} -\arguments{ -\item{search.text}{A single length \code{character} vector, containing -search text. Provided search pattern is searched in all fields (mod format, -author and title). Prefixes can be added to keywords for inclusive or exclusive -searches. For details see \url{https://www.exotica.org.uk/wiki/Modland#Searching}. -Note that modLand contains a wide range of tracker files, only mod-files -are supported by the \code{ProTrackR} package. It is therefore advisable to add the -keyword `mod' to the search string.} - -\item{format}{A single length \code{character} vector, indicating the -tracker file format. ``Protracker`' is the option that is most likely to work in this package.} - -\item{author}{A single length \code{character} vector, indicating the -module author name. Can be obtained from a \code{modLand.search.mod}.} - -\item{title}{A single length \code{character} vector, indicating the -module title. Can be obtained from a \code{modLand.search.mod}.} - -\item{mirror}{A single length \code{character} vector. Should contain one of the -mirrors listed in the `usage' section. Select a mirror site from which -the module file needs to be downloaded.} - -\item{...}{Argument that are passed on to \code{\link{read.module}}.} -} -\value{ -\code{modLand.search.mod} returns a \code{data.frame}. -The \code{data.frame} contains a search result in each row. -The data.frame contains a number of columns, each containing -\code{character} strings. The column \verb{title' contains the mod file name; The column named }author' contains the author name; the column named -\verb{format' contains the tracker file format (only ``Protracker}' -is supported by this package); The collumn \verb{collect' contains modLand collections in which the mod is included; the column named }url' contains a download link for the \verb{ogg'-file generated on the modLand server from the mod file. Note that ogg-files are not supported by the ProTrackR package. Use }modLand.download.mod` to download -the mod file. - -\code{modLand.download.mod} attempts to download the specified mod -file and return it as a \code{\link{PTModule}} object. It will throw -errors when the mod file is not available or when there are network -problems... -} -\description{ -\url{https://modland.com} is on of the largest online archive of module files. These functions -will assist in accessing this archive. -} -\details{ -Like the \url{https://modarchive.org}, modland provides access to a large collection of module files. -Compared to the \link{modArchive}, modLand provides limited searching features. However, it -does not require an API key. - -The functions documented here are provided as a convenience and depend -on third party services. Note that continuity of these services cannot -be guaranteed. - -Use \code{modLand.search.mod} to search through the modLand collection. - -Use \code{modLand.download.mod} to download a specific mod file as an S4 object. -} -\examples{ -\dontrun{ -## Search for a funky tune: - -modland <- modLand.search.mod("elekfunk mod") - -## The ogg file can be downloaded (in this case to the tempdir()), -## but it is not supported by the ProTrackR package... - -utils::download.file(modland$url[1], tempdir()) - -## Instead, use the following approach to download the module: - -mod <- modLand.download.mod(modland$format[1], - modland$author[1], - modland$title[1]) - -} -} -\author{ -Pepijn de Vries -} diff --git a/man/modToWave.Rd b/man/modToWave.Rd index 0bb6101..f1b6abe 100644 --- a/man/modToWave.Rd +++ b/man/modToWave.Rd @@ -122,11 +122,9 @@ This should not be a problem if you're not concerned with producing an accurate Amiga timbre. } \examples{ -\dontrun{ data(mod.intro) wav <- modToWave(mod.intro) } -} \seealso{ Other module.operations: \code{\link{PTModule-class}}, diff --git a/man/playMod.Rd b/man/playMod.Rd index f6e6f9b..ca12db0 100644 --- a/man/playMod.Rd +++ b/man/playMod.Rd @@ -5,7 +5,7 @@ \alias{playMod,PTModule-method} \title{Play PTModule objects} \usage{ -\S4method{playMod}{PTModule}(mod, wait = T, ...) +\S4method{playMod}{PTModule}(mod, wait = TRUE, ...) } \arguments{ \item{mod}{A \code{\link{PTModule}} object to be played.} @@ -35,11 +35,11 @@ balance between speed, quality and accuracy. See the documentation of the \code{\link{modToWave}} method for the control you have on these aspects. } \examples{ -\dontrun{ -data("mod.intro") +if (interactive()) { + data("mod.intro") -## play the module and capture the audio Wave -wav <- playMod(mod.intro) + ## play the module and capture the audio Wave + wav <- playMod(mod.intro) } } \seealso{ diff --git a/man/playSample.Rd b/man/playSample.Rd index 7399fb6..4e57f1a 100644 --- a/man/playSample.Rd +++ b/man/playSample.Rd @@ -6,9 +6,9 @@ \alias{playSample,PTModule-method} \title{Play audio samples} \usage{ -\S4method{playSample}{PTSample}(x, silence = 0, wait = T, note = "C-3", loop = 1, ...) +\S4method{playSample}{PTSample}(x, silence = 0, wait = TRUE, note = "C-3", loop = 1, ...) -\S4method{playSample}{PTModule}(x, silence = 0, wait = T, note = "C-3", loop = 1, ...) +\S4method{playSample}{PTModule}(x, silence = 0, wait = TRUE, note = "C-3", loop = 1, ...) } \arguments{ \item{x}{Either a \code{\link{PTSample}} or a \code{\link{PTModule}} object. @@ -60,25 +60,24 @@ as specified for the \code{\link{PTSample}} will be applied when playing the sample. } \examples{ -\dontrun{ -data("mod.intro") +if (interactive()) { + data("mod.intro") -## play all samples in mod.intro: -playSample(mod.intro, 0.2, loop = 0.5) + ## play all samples in mod.intro: + playSample(mod.intro, 0.2, loop = 0.5) -## play a chromatic scale using sample number 3: -for (note in c("A-2", "A#2", "B-2", "C-3", "C#3", - "D-3", "D#3", "E-3", "F-3", "F#3", - "G-3", "G#3")) -{ - playSample(PTSample(mod.intro, 3), note = note, silence = 0.05, loop = 0.4) -} + ## play a chromatic scale using sample number 3: + for (note in c("A-2", "A#2", "B-2", "C-3", "C#3", + "D-3", "D#3", "E-3", "F-3", "F#3", + "G-3", "G#3")) + { + playSample(PTSample(mod.intro, 3), note = note, silence = 0.05, loop = 0.4) + } -## play the sample at a rate based on a specific -## video mode and finetune: -playSample(PTSample(mod.intro, 3), video = "NTSC", finetune = -5) + ## play the sample at a rate based on a specific + ## video mode and finetune: + playSample(PTSample(mod.intro, 3), video = "NTSC", finetune = -5) } - } \seealso{ Other sample.operations: diff --git a/man/playWave.Rd b/man/playWave.Rd index 955b4a4..4689f81 100644 --- a/man/playWave.Rd +++ b/man/playWave.Rd @@ -6,9 +6,9 @@ \alias{playWave,WaveMC-method} \title{Play Wave objects} \usage{ -\S4method{playWave}{Wave}(wave, wait = T) +\S4method{playWave}{Wave}(wave, wait = TRUE) -\S4method{playWave}{WaveMC}(wave, wait = T) +\S4method{playWave}{WaveMC}(wave, wait = TRUE) } \arguments{ \item{wave}{An object of class \code{\link[tuneR:Wave]{tuneR::Wave}} or @@ -29,7 +29,7 @@ Use the command line \code{\link[audio:play]{audio::play}} function from the \code{audio} package to play \code{\link[tuneR:Wave]{tuneR::Wave}} objects. } \details{ -As the \code{\link{tuneR}} package play-function relies on external +As the \code{tuneR} package play-function relies on external players, this method is provided as a convenient approach to play samples in the R console, using the \code{audio} package. Wave objects are played at the rate as specified in the object. Of course @@ -37,13 +37,13 @@ you can also play the \code{Wave} objects with the \code{tuneR} implementation of \code{\link[tuneR:play]{tuneR::play}}, by calling \code{tuneR::play(wave)}. } \examples{ -\dontrun{ -data(mod.intro) +if (interactive()) { + data(mod.intro) -## PTSample objects can also be -## played with this function as they -## are a child of the Wave object: -playWave(PTSample(mod.intro, 2)) + ## PTSample objects can also be + ## played with this function as they + ## are a child of the Wave object: + playWave(PTSample(mod.intro, 2)) } } \seealso{ diff --git a/man/playingtable.Rd b/man/playingtable.Rd index 9b04cce..c11f67a 100644 --- a/man/playingtable.Rd +++ b/man/playingtable.Rd @@ -12,8 +12,8 @@ speed = 6, tempo = 125, video = c("PAL", "NTSC"), - play.once = T, - verbose = T + play.once = TRUE, + verbose = TRUE ) } \arguments{ @@ -98,11 +98,9 @@ the four tracks in the module.} } } \examples{ -\dontrun{ data(mod.intro) pt <- playingtable(mod.intro) } -} \seealso{ Other module.operations: \code{\link{PTModule-class}}, diff --git a/man/plot.Rd b/man/plot.Rd index 9ed3cd2..680f108 100644 --- a/man/plot.Rd +++ b/man/plot.Rd @@ -6,7 +6,7 @@ \alias{plot,PTModule,missing-method} \title{Plot a PTModule object} \usage{ -\S4method{plot}{PTModule,missing}(x, y, plot.loop.positions = T, ...) +\S4method{plot}{PTModule,missing}(x, y, plot.loop.positions = TRUE, ...) } \arguments{ \item{x}{A \code{\link{PTModule}} object for which the diff --git a/man/rawToPTModule.Rd b/man/rawToPTModule.Rd index 8ad1c8e..a8ac2f1 100644 --- a/man/rawToPTModule.Rd +++ b/man/rawToPTModule.Rd @@ -5,7 +5,7 @@ \alias{rawToPTModule,raw-method} \title{Convert a vector of raw data into a PTModule object} \usage{ -\S4method{rawToPTModule}{raw}(x, ignore.validity = F) +\S4method{rawToPTModule}{raw}(x, ignore.validity = FALSE) } \arguments{ \item{x}{A vector of \code{raw} data, conform ProTracker file specs.} @@ -32,7 +32,6 @@ package. Use \code{\link{as.raw}} to achieve the inverse. } \examples{ -\dontrun{ ## convert the example mod into raw data data("mod.intro") mod.raw <- as.raw(mod.intro) @@ -43,7 +42,6 @@ mod.restored <- rawToPTModule(mod.raw) ## In this case the result is identical to the original: identical(mod.restored, mod.intro) } -} \seealso{ Other module.operations: \code{\link{PTModule-class}}, diff --git a/man/read.module.Rd b/man/read.module.Rd index c6ddcd0..b3aca92 100644 --- a/man/read.module.Rd +++ b/man/read.module.Rd @@ -9,13 +9,13 @@ \alias{read.module,ANY,logical-method} \title{Read a ProTracker module file} \usage{ -\S4method{read.module}{character,logical}(file, ignore.validity = F) +\S4method{read.module}{character,logical}(file, ignore.validity = FALSE) -\S4method{read.module}{ANY,missing}(file, ignore.validity = F) +\S4method{read.module}{ANY,missing}(file, ignore.validity = FALSE) -\S4method{read.module}{ANY,missing}(file, ignore.validity = F) +\S4method{read.module}{ANY,missing}(file, ignore.validity = FALSE) -\S4method{read.module}{ANY,logical}(file, ignore.validity = F) +\S4method{read.module}{ANY,logical}(file, ignore.validity = FALSE) } \arguments{ \item{file}{either a filename or a file connection, that @@ -50,17 +50,17 @@ It should also be able to read most of the .mod files in \href{https://modarchive.org/}{The Mod Archive}. } \examples{ -\dontrun{ - ## first create an module file from example data: data("mod.intro") -write.module(mod.intro, "intro.mod") + +f <- tempfile(fileext = ".mod") +write.module(mod.intro, f) ## read the module: -mod <- read.module("intro.mod") +mod <- read.module(f) ## or create a connection yourself: -con <- file("intro.mod", "rb") +con <- file(f, "rb") ## note that you can also read from URL connections! mod2 <- read.module(con) @@ -68,7 +68,6 @@ mod2 <- read.module(con) ## don't forget to close the file: close(con) } -} \references{ \url{https://wiki.multimedia.cx/index.php?title=Protracker_Module} } diff --git a/man/read.sample.Rd b/man/read.sample.Rd index ad68045..2f08746 100644 --- a/man/read.sample.Rd +++ b/man/read.sample.Rd @@ -42,16 +42,15 @@ As per ProTracker standards, a sample should have an even length is added to the end. } \examples{ -\dontrun{ data("mod.intro") +f <- tempfile(fileext = ".iff") ## create an audio file which we can then read: -write.sample(PTSample(mod.intro, 2), "snaredrum.iff", "8svx") +write.sample(PTSample(mod.intro, 2), f, "8svx") ## read the created sample: -snare <- read.sample("snaredrum.iff", "8svx") +snare <- read.sample(f, "8svx") print(snare) -} } \seealso{ diff --git a/man/write.module.Rd b/man/write.module.Rd index c43f4e9..59945a9 100644 --- a/man/write.module.Rd +++ b/man/write.module.Rd @@ -30,21 +30,20 @@ of ProTracker 2.3A. This means that the routine may not be able to write files that ar compatible with later or earlier ProTracker versions. } \examples{ -\dontrun{ ## get the PTModule object provided with the ProTrackR package data("mod.intro") +f <- tempfile(fileext = ".mod") ## save the object as a valid ProTracker module file: -write.module(mod.intro, "intro.mod") +write.module(mod.intro, f) ## or create the connection yourself: -con <- file("intro2.mod", "wb") +con <- file(f, "wb") write.module(mod.intro, con) ## don't forget to close the connection after you're done: close(con) } -} \references{ \url{https://wiki.multimedia.cx/index.php?title=Protracker_Module} } diff --git a/man/write.sample.Rd b/man/write.sample.Rd index 72be2c9..3f54acc 100644 --- a/man/write.sample.Rd +++ b/man/write.sample.Rd @@ -34,19 +34,16 @@ files also known as "iff" files). In addition they can be exported as raw data, where each byte simply represents a signed integer value of the waveform. } \examples{ -\dontrun{ data("mod.intro") ## Export the second sample of mod.intro as a wav file: -write.sample(PTSample(mod.intro, 2), "snaredrum.wav", "wav") +write.sample(PTSample(mod.intro, 2), tempfile(fileext = ".wav"), "wav") ## Export the second sample of mod.intro as an 8svx file: -write.sample(PTSample(mod.intro, 2), "snaredrum.iff", "8svx") +write.sample(PTSample(mod.intro, 2), tempfile(fileext = ".iff"), "8svx") ## Export the second sample of mod.intro as a raw file: -write.sample(PTSample(mod.intro, 2), "snaredrum.raw", "raw") -} - +write.sample(PTSample(mod.intro, 2), tempfile(fileext = ".raw"), "raw") } \seealso{ Other sample.operations: From 5e4dfbb0bbdd07cc16d8abee8c3b2d4a543093d8 Mon Sep 17 00:00:00 2001 From: pepijn-devries Date: Sun, 12 Jan 2025 01:29:58 +0100 Subject: [PATCH 2/2] Fix for non-Windows machines --- R/10MODPlugHelpers.r | 10 ++++++---- man/PTPatternToMODPlug.Rd | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/R/10MODPlugHelpers.r b/R/10MODPlugHelpers.r index c3ac0b9..697d19e 100644 --- a/R/10MODPlugHelpers.r +++ b/R/10MODPlugHelpers.r @@ -167,7 +167,7 @@ MODPlugToPTPattern <- function(text = NULL, what = c("PTPattern", "PTBlock")) { #' @param to.clipboard A `logical` value, indicating whether the #' result should be copied to the system's clipboard (`TRUE`) or #' should be returned as a `vector` of `character`s -#' (`FALSE`). +#' (`FALSE`). Note that copying to clipboard only works on Windows machines #' @returns Returns an invisible `NULL` when #' argument `to.clipboard` is set to `TRUE`. #' Returns an Open MODPlug Tracker flavoured pattern table as @@ -184,8 +184,10 @@ MODPlugToPTPattern <- function(text = NULL, what = c("PTPattern", "PTBlock")) { #' ## The result is placed on the system clipboard. #' ## You can check by pasting it into a text #' ## editor, or better yet, the MODPlug Tracker. -#' -#' PTPatternToMODPlug(pattern) +#' +#' if (.Platform$OS.type == "windows") { +#' PTPatternToMODPlug(pattern) +#' } #' #' ## If you want to handle the pattern data #' ## in R: @@ -195,7 +197,7 @@ MODPlugToPTPattern <- function(text = NULL, what = c("PTPattern", "PTBlock")) { #' ## We can do the same with a block: #' #' block <- PTBlock(pattern, 1:10, 2:3) -#' PTPatternToMODPlug(block) +#' PTPatternToMODPlug(block, FALSE) #' @author Pepijn de Vries #' @family MODPlug.operations #' @family pattern.operations diff --git a/man/PTPatternToMODPlug.Rd b/man/PTPatternToMODPlug.Rd index 20c456e..7fbeeed 100644 --- a/man/PTPatternToMODPlug.Rd +++ b/man/PTPatternToMODPlug.Rd @@ -14,7 +14,7 @@ MODPlug Tracker pattern should be created.} \item{to.clipboard}{A \code{logical} value, indicating whether the result should be copied to the system's clipboard (\code{TRUE}) or should be returned as a \code{vector} of \code{character}s -(\code{FALSE}).} +(\code{FALSE}). Note that copying to clipboard only works on Windows machines} } \value{ Returns an invisible \code{NULL} when @@ -41,7 +41,9 @@ pattern <- PTPattern(mod.intro, 1) ## You can check by pasting it into a text ## editor, or better yet, the MODPlug Tracker. -PTPatternToMODPlug(pattern) +if (.Platform$OS.type == "windows") { + PTPatternToMODPlug(pattern) +} ## If you want to handle the pattern data ## in R: @@ -51,7 +53,7 @@ patModPlug <- PTPatternToMODPlug(pattern, FALSE) ## We can do the same with a block: block <- PTBlock(pattern, 1:10, 2:3) -PTPatternToMODPlug(block) +PTPatternToMODPlug(block, FALSE) } \seealso{ Other MODPlug.operations: