diff --git a/DESCRIPTION b/DESCRIPTION index 12383ef..c492243 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: ProTrackR2 Title: Manipulate and Play 'ProTracker' Modules -Version: 0.0.6.0014 +Version: 0.0.6.0015 Authors@R: c( person("Pepijn", "de Vries", role = c("aut", "cre"), email = "pepijn.devries@outlook.com", diff --git a/NEWS.md b/NEWS.md index 609d90e..9de156f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -ProTrackR2 v0.0.6.0014 +ProTrackR2 v0.0.6.0015 ------------- * Implemented `as_pt2cell()` and `as_pt2celllist()` diff --git a/data-raw/DATASET.R b/data-raw/DATASET.R index 6179a95..118b1fa 100644 --- a/data-raw/DATASET.R +++ b/data-raw/DATASET.R @@ -19,11 +19,5 @@ if (!requireNamespace("ProTrackR")) { dur2 <- c(dur2, as.numeric(endtime - starttime, "secs")) } mean(dur1)/mean(dur2) - if (requireNamespace("av")) { - tempsmp <- tempfile(fileext = ".wav") - pt2_write_sample(mod2$samples[[1]], tempsmp) - samp <- av::read_audio_bin(tempsmp) - av::av_audio_convert( - tempsmp, "data-raw/test-sample.aiff", format = "u8") - } + } diff --git a/inst/mod.intro b/inst/mod.intro index be99674..53bb2c2 100644 Binary files a/inst/mod.intro and b/inst/mod.intro differ diff --git a/src/pt2-clone/pt2_sampler.c b/src/pt2-clone/pt2_sampler.c index 2a7f8d7..dd2dc3d 100644 --- a/src/pt2-clone/pt2_sampler.c +++ b/src/pt2-clone/pt2_sampler.c @@ -19,25 +19,25 @@ sampler_t sampler; // globalized -void killSample(void) -{ - if (editor.sampleZero) - return; - - turnOffVoices(); - moduleSample_t *s = &song->samples[editor.currSample]; - - s->fineTune = 0; - s->volume = 0; - s->length = 0; - s->loopStart = 0; - s->loopLength = 2; - - memset(s->text, 0, sizeof (s->text)); - memset(&song->sampleData[(editor.currSample * config.maxSampleLength)], 0, config.maxSampleLength); - - editor.samplePos = 0; -} +// void killSample(void) +// { +// if (editor.sampleZero) +// return; +// +// turnOffVoices(); +// moduleSample_t *s = &song->samples[editor.currSample]; +// +// s->fineTune = 0; +// s->volume = 0; +// s->length = 0; +// s->loopStart = 0; +// s->loopLength = 2; +// +// memset(s->text, 0, sizeof (s->text)); +// memset(&song->sampleData[(editor.currSample * config.maxSampleLength)], 0, config.maxSampleLength); +// +// editor.samplePos = 0; +// } void upSample(void) { @@ -130,31 +130,31 @@ void fixSampleBeep(moduleSample_t *s) fixSampleBeep2(s, song->sampleData); } -void updateSamplePos(void) -{ - moduleSample_t *s; - - assert(editor.currSample >= 0 && editor.currSample <= 30); - if (editor.currSample >= 0 && editor.currSample <= 30) - { - s = &song->samples[editor.currSample]; - if (editor.samplePos > s->length) - editor.samplePos = s->length; - - } -} - -void fillSampleFilterUndoBuffer(void) -{ - moduleSample_t *s; - - assert(editor.currSample >= 0 && editor.currSample <= 30); - if (editor.currSample >= 0 && editor.currSample <= 30) - { - s = &song->samples[editor.currSample]; - memcpy(sampler.sampleUndoCopy, &song->sampleData[s->offset], s->length); - } -} +// void updateSamplePos(void) +// { +// moduleSample_t *s; +// +// assert(editor.currSample >= 0 && editor.currSample <= 30); +// if (editor.currSample >= 0 && editor.currSample <= 30) +// { +// s = &song->samples[editor.currSample]; +// if (editor.samplePos > s->length) +// editor.samplePos = s->length; +// +// } +// } +// +// void fillSampleFilterUndoBuffer(void) +// { +// moduleSample_t *s; +// +// assert(editor.currSample >= 0 && editor.currSample <= 30); +// if (editor.currSample >= 0 && editor.currSample <= 30) +// { +// s = &song->samples[editor.currSample]; +// memcpy(sampler.sampleUndoCopy, &song->sampleData[s->offset], s->length); +// } +// } // static int8_t getScaledSample(int32_t index) // { @@ -206,7 +206,7 @@ void highPassSample(int32_t cutOff) if (dSampleData == NULL) return; - fillSampleFilterUndoBuffer(); + //fillSampleFilterUndoBuffer(); // setup filter coefficients @@ -291,7 +291,7 @@ void lowPassSample(int32_t cutOff) if (dSampleData == NULL) return; - fillSampleFilterUndoBuffer(); + //fillSampleFilterUndoBuffer(); // setup filter coefficients @@ -343,61 +343,61 @@ void lowPassSample(int32_t cutOff) fixSampleBeep(s); } -void redoSampleData(int8_t sample) -{ - if (editor.sampleZero) - return; - - assert(sample >= 0 && sample <= 30); - moduleSample_t *s = &song->samples[sample]; - - turnOffVoices(); - - if (editor.smpRedoBuffer[sample] != NULL && editor.smpRedoLengths[sample] > 0) - { - memcpy(&song->sampleData[s->offset], editor.smpRedoBuffer[sample], editor.smpRedoLengths[sample]); - - if (editor.smpRedoLengths[sample] < config.maxSampleLength) - memset(&song->sampleData[s->offset + editor.smpRedoLengths[sample]], 0, config.maxSampleLength - editor.smpRedoLengths[sample]); - } - else - { - memset(&song->sampleData[s->offset], 0, config.maxSampleLength); - } - - s->fineTune = editor.smpRedoFinetunes[sample]; - s->volume = editor.smpRedoVolumes[sample]; - s->length = editor.smpRedoLengths[sample]; - s->loopStart = editor.smpRedoLoopStarts[sample]; - s->loopLength = (editor.smpRedoLoopLengths[sample] < 2) ? 2 : editor.smpRedoLoopLengths[sample]; - - editor.samplePos = 0; -} - -void fillSampleRedoBuffer(int8_t sample) -{ - assert(sample >= 0 && sample <= 30); - moduleSample_t *s = &song->samples[sample]; - - if (editor.smpRedoBuffer[sample] != NULL) - { - free(editor.smpRedoBuffer[sample]); - editor.smpRedoBuffer[sample] = NULL; - } - - editor.smpRedoFinetunes[sample] = s->fineTune; - editor.smpRedoVolumes[sample] = s->volume; - editor.smpRedoLengths[sample] = s->length; - editor.smpRedoLoopStarts[sample] = s->loopStart; - editor.smpRedoLoopLengths[sample] = s->loopLength; - - if (s->length > 0) - { - editor.smpRedoBuffer[sample] = (int8_t *)malloc(s->length); - if (editor.smpRedoBuffer[sample] != NULL) - memcpy(editor.smpRedoBuffer[sample], &song->sampleData[s->offset], s->length); - } -} +// void redoSampleData(int8_t sample) +// { +// if (editor.sampleZero) +// return; +// +// assert(sample >= 0 && sample <= 30); +// moduleSample_t *s = &song->samples[sample]; +// +// turnOffVoices(); +// +// if (editor.smpRedoBuffer[sample] != NULL && editor.smpRedoLengths[sample] > 0) +// { +// memcpy(&song->sampleData[s->offset], editor.smpRedoBuffer[sample], editor.smpRedoLengths[sample]); +// +// if (editor.smpRedoLengths[sample] < config.maxSampleLength) +// memset(&song->sampleData[s->offset + editor.smpRedoLengths[sample]], 0, config.maxSampleLength - editor.smpRedoLengths[sample]); +// } +// else +// { +// memset(&song->sampleData[s->offset], 0, config.maxSampleLength); +// } +// +// s->fineTune = editor.smpRedoFinetunes[sample]; +// s->volume = editor.smpRedoVolumes[sample]; +// s->length = editor.smpRedoLengths[sample]; +// s->loopStart = editor.smpRedoLoopStarts[sample]; +// s->loopLength = (editor.smpRedoLoopLengths[sample] < 2) ? 2 : editor.smpRedoLoopLengths[sample]; +// +// editor.samplePos = 0; +// } +// +// void fillSampleRedoBuffer(int8_t sample) +// { +// assert(sample >= 0 && sample <= 30); +// moduleSample_t *s = &song->samples[sample]; +// +// if (editor.smpRedoBuffer[sample] != NULL) +// { +// free(editor.smpRedoBuffer[sample]); +// editor.smpRedoBuffer[sample] = NULL; +// } +// +// editor.smpRedoFinetunes[sample] = s->fineTune; +// editor.smpRedoVolumes[sample] = s->volume; +// editor.smpRedoLengths[sample] = s->length; +// editor.smpRedoLoopStarts[sample] = s->loopStart; +// editor.smpRedoLoopLengths[sample] = s->loopLength; +// +// if (s->length > 0) +// { +// editor.smpRedoBuffer[sample] = (int8_t *)malloc(s->length); +// if (editor.smpRedoBuffer[sample] != NULL) +// memcpy(editor.smpRedoBuffer[sample], &song->sampleData[s->offset], s->length); +// } +// } bool allocSamplerVars(void) // must be called after config is loaded { @@ -725,142 +725,142 @@ void filterSample(int32_t sample, bool ignoreMark) fixSampleBeep(s); } -void samplerSamCopy(void) -{ - if (editor.sampleZero) - return; - - assert(editor.currSample >= 0 && editor.currSample <= 30); - moduleSample_t *s = &song->samples[editor.currSample]; - - if (s->length == 0) - return; - - if (editor.markStartOfs == -1) - return; - - if (editor.markEndOfs-editor.markStartOfs <= 0) - return; - - sampler.copyBufSize = editor.markEndOfs - editor.markStartOfs; - - if ((int32_t)(editor.markStartOfs + sampler.copyBufSize) > config.maxSampleLength) - return; - - memcpy(sampler.copyBuf, &song->sampleData[s->offset+editor.markStartOfs], sampler.copyBufSize); -} - -void samplerSamPaste(void) -{ - if (editor.sampleZero) - return; - - if (sampler.copyBuf == NULL || sampler.copyBufSize == 0) - return; - - assert(editor.currSample >= 0 && editor.currSample <= 30); - - moduleSample_t *s = &song->samples[editor.currSample]; - if (s->length > 0 && editor.markStartOfs == -1) - return; - - int32_t markStart = editor.markStartOfs; - if (s->length == 0) - markStart = 0; - - if (s->length+sampler.copyBufSize > config.maxSampleLength) - return; - - int8_t *tmpBuf = (int8_t *)malloc(config.maxSampleLength); - if (tmpBuf == NULL) - return; - - uint32_t readPos = 0; - turnOffVoices(); - - // copy start part - if (markStart > 0) - { - memcpy(&tmpBuf[readPos], &song->sampleData[s->offset], markStart); - readPos += markStart; - } - - // copy actual buffer - memcpy(&tmpBuf[readPos], sampler.copyBuf, sampler.copyBufSize); - - // copy end part - if (markStart >= 0) - { - readPos += sampler.copyBufSize; - - if (s->length-markStart > 0) - memcpy(&tmpBuf[readPos], &song->sampleData[s->offset+markStart], s->length - markStart); - } - - int32_t newLength = (s->length + sampler.copyBufSize) & ~1; - if (newLength > config.maxSampleLength) - newLength = config.maxSampleLength; - - sampler.samLength = s->length = newLength; - - if (s->loopLength > 2) // loop enabled? - { - if (markStart > s->loopStart) - { - if (markStart < s->loopStart+s->loopLength) - { - // we pasted data inside the loop, increase loop length - - if (s->loopLength+sampler.copyBufSize > config.maxSampleLength) - { - s->loopStart = 0; - s->loopLength = 2; - } - else - { - s->loopLength = (s->loopLength + sampler.copyBufSize) & config.maxSampleLength; - if (s->loopStart+s->loopLength > s->length) - { - s->loopStart = 0; - s->loopLength = 2; - } - } - } - - // we pasted data after the loop, don't modify loop points - } - else - { - // we pasted data before the loop, adjust loop start point - if (s->loopStart+sampler.copyBufSize > config.maxSampleLength) - { - s->loopStart = 0; - s->loopLength = 2; - } - else - { - s->loopStart = (s->loopStart + sampler.copyBufSize) & config.maxSampleLength; - if (s->loopStart+s->loopLength > s->length) - { - s->loopStart = 0; - s->loopLength = 2; - } - } - } - } - - memcpy(&song->sampleData[s->offset], tmpBuf, s->length); - - // clear data after sample's length (if present) - if (s->length < config.maxSampleLength) - memset(&song->sampleData[s->offset+s->length], 0, config.maxSampleLength - s->length); - - free(tmpBuf); - - editor.markStartOfs = -1; - - fixSampleBeep(s); -} +// void samplerSamCopy(void) +// { +// if (editor.sampleZero) +// return; +// +// assert(editor.currSample >= 0 && editor.currSample <= 30); +// moduleSample_t *s = &song->samples[editor.currSample]; +// +// if (s->length == 0) +// return; +// +// if (editor.markStartOfs == -1) +// return; +// +// if (editor.markEndOfs-editor.markStartOfs <= 0) +// return; +// +// sampler.copyBufSize = editor.markEndOfs - editor.markStartOfs; +// +// if ((int32_t)(editor.markStartOfs + sampler.copyBufSize) > config.maxSampleLength) +// return; +// +// memcpy(sampler.copyBuf, &song->sampleData[s->offset+editor.markStartOfs], sampler.copyBufSize); +// } +// +// void samplerSamPaste(void) +// { +// if (editor.sampleZero) +// return; +// +// if (sampler.copyBuf == NULL || sampler.copyBufSize == 0) +// return; +// +// assert(editor.currSample >= 0 && editor.currSample <= 30); +// +// moduleSample_t *s = &song->samples[editor.currSample]; +// if (s->length > 0 && editor.markStartOfs == -1) +// return; +// +// int32_t markStart = editor.markStartOfs; +// if (s->length == 0) +// markStart = 0; +// +// if (s->length+sampler.copyBufSize > config.maxSampleLength) +// return; +// +// int8_t *tmpBuf = (int8_t *)malloc(config.maxSampleLength); +// if (tmpBuf == NULL) +// return; +// +// uint32_t readPos = 0; +// turnOffVoices(); +// +// // copy start part +// if (markStart > 0) +// { +// memcpy(&tmpBuf[readPos], &song->sampleData[s->offset], markStart); +// readPos += markStart; +// } +// +// // copy actual buffer +// memcpy(&tmpBuf[readPos], sampler.copyBuf, sampler.copyBufSize); +// +// // copy end part +// if (markStart >= 0) +// { +// readPos += sampler.copyBufSize; +// +// if (s->length-markStart > 0) +// memcpy(&tmpBuf[readPos], &song->sampleData[s->offset+markStart], s->length - markStart); +// } +// +// int32_t newLength = (s->length + sampler.copyBufSize) & ~1; +// if (newLength > config.maxSampleLength) +// newLength = config.maxSampleLength; +// +// sampler.samLength = s->length = newLength; +// +// if (s->loopLength > 2) // loop enabled? +// { +// if (markStart > s->loopStart) +// { +// if (markStart < s->loopStart+s->loopLength) +// { +// // we pasted data inside the loop, increase loop length +// +// if (s->loopLength+sampler.copyBufSize > config.maxSampleLength) +// { +// s->loopStart = 0; +// s->loopLength = 2; +// } +// else +// { +// s->loopLength = (s->loopLength + sampler.copyBufSize) & config.maxSampleLength; +// if (s->loopStart+s->loopLength > s->length) +// { +// s->loopStart = 0; +// s->loopLength = 2; +// } +// } +// } +// +// // we pasted data after the loop, don't modify loop points +// } +// else +// { +// // we pasted data before the loop, adjust loop start point +// if (s->loopStart+sampler.copyBufSize > config.maxSampleLength) +// { +// s->loopStart = 0; +// s->loopLength = 2; +// } +// else +// { +// s->loopStart = (s->loopStart + sampler.copyBufSize) & config.maxSampleLength; +// if (s->loopStart+s->loopLength > s->length) +// { +// s->loopStart = 0; +// s->loopLength = 2; +// } +// } +// } +// } +// +// memcpy(&song->sampleData[s->offset], tmpBuf, s->length); +// +// // clear data after sample's length (if present) +// if (s->length < config.maxSampleLength) +// memset(&song->sampleData[s->offset+s->length], 0, config.maxSampleLength - s->length); +// +// free(tmpBuf); +// +// editor.markStartOfs = -1; +// +// fixSampleBeep(s); +// } // static void playCurrSample(uint8_t chn, int32_t startOffset, int32_t endOffset, bool playWaveformFlag) // { @@ -919,49 +919,49 @@ void samplerSamPaste(void) // // } -void samplerLoopToggle(void) -{ - if (editor.sampleZero) - return; - - assert(editor.currSample >= 0 && editor.currSample <= 30); - - moduleSample_t *s = &song->samples[editor.currSample]; - if (s->length < 2) - return; - - turnOffVoices(); - - if (s->loopStart+s->loopLength > 2) - { - // disable loop - - sampler.tmpLoopStart = s->loopStart; - sampler.tmpLoopLength = s->loopLength; - - s->loopStart = 0; - s->loopLength = 2; - } - else - { - // enable loop - - if (sampler.tmpLoopStart == 0 && sampler.tmpLoopLength == 0) - { - s->loopStart = 0; - s->loopLength = s->length; - } - else - { - s->loopStart = sampler.tmpLoopStart; - s->loopLength = sampler.tmpLoopLength; - - if (s->loopStart+s->loopLength > s->length) - { - s->loopStart = 0; - s->loopLength = s->length; - } - } - } - updatePaulaLoops(); -} +// void samplerLoopToggle(void) +// { +// if (editor.sampleZero) +// return; +// +// assert(editor.currSample >= 0 && editor.currSample <= 30); +// +// moduleSample_t *s = &song->samples[editor.currSample]; +// if (s->length < 2) +// return; +// +// turnOffVoices(); +// +// if (s->loopStart+s->loopLength > 2) +// { +// // disable loop +// +// sampler.tmpLoopStart = s->loopStart; +// sampler.tmpLoopLength = s->loopLength; +// +// s->loopStart = 0; +// s->loopLength = 2; +// } +// else +// { +// // enable loop +// +// if (sampler.tmpLoopStart == 0 && sampler.tmpLoopLength == 0) +// { +// s->loopStart = 0; +// s->loopLength = s->length; +// } +// else +// { +// s->loopStart = sampler.tmpLoopStart; +// s->loopLength = sampler.tmpLoopLength; +// +// if (s->loopStart+s->loopLength > s->length) +// { +// s->loopStart = 0; +// s->loopLength = s->length; +// } +// } +// } +// updatePaulaLoops(); +// } diff --git a/tests/testthat/test_io.R b/tests/testthat/test_io.R index 6e58d71..7910910 100644 --- a/tests/testthat/test_io.R +++ b/tests/testthat/test_io.R @@ -3,11 +3,13 @@ sample <- pt2_sample(mod, 0L) smpfile_raw <- tempfile(fileext = ".raw") smpfile_iff <- tempfile(fileext = ".iff") smpfile_wav <- tempfile(fileext = ".wav") -smpfile_aiff <- "https://github.com/pepijn-devries/ProTrackR2/blob/master/data-raw/test-sample.aiff" +smpfile_aiff <- "https://github.com/pepijn-devries/ProTrackR2/raw/refs/heads/master/data-raw/test-sample.aiff" -test_that("Writing a mod works", { +test_that("Writing and reading a mod works", { expect_no_error({ - pt2_write_mod(mod, tempfile(fileext = ".mod")) + tf <- tempfile(fileext = ".mod") + pt2_write_mod(mod, tf) + pt2_read_mod(tf) }) }) @@ -21,10 +23,15 @@ test_that("Writing raw samples will warn user", { test_that("Reading sample works", { skip_if_offline() - expect_no_error({ + expect_true({ samp_raw <- pt2_read_sample(smpfile_raw) samp_iff <- pt2_read_sample(smpfile_iff) samp_wav <- pt2_read_sample(smpfile_wav) samp_aiff <- pt2_read_sample(smpfile_aiff) + all(samp_iff == samp_wav) && + all(samp_iff == samp_aiff) && + all(samp_iff == samp_raw) && + pt2_loop_start(samp_iff) == 762 && + pt2_loop_length(samp_iff) == 276 }) }) diff --git a/vignettes/ProTrackR_vs_ProTrackR2.Rmd b/vignettes/ProTrackR_vs_ProTrackR2.Rmd index f7d4d22..a62f91d 100644 --- a/vignettes/ProTrackR_vs_ProTrackR2.Rmd +++ b/vignettes/ProTrackR_vs_ProTrackR2.Rmd @@ -93,7 +93,12 @@ mod_old <- new("PTModule") mod_new <- pt2_new_mod("my mod") ## *Old* reading a module: -mod_old <- read.module(pt2_demo()) +## Note that `ProTrackR` does not support compressed modules, +## so we first need to create a file that the old library can read: +file_decompressed <- tempfile() +pt2_write_mod(pt2_read_mod(pt2_demo()), file_decompressed) +## Now the old library can actually read it +mod_old <- read.module(file_decompressed) ## *New* way of creating a blank module: mod_new <- pt2_read_mod(pt2_demo())