diff --git a/src/definitions.h b/src/definitions.h index e3036837b2..740767bb71 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -2,6 +2,12 @@ #define ALPHA_OR_BETA_VERSION 1 // Whether to compile with additional error-checking +#if !defined(NDEBUG) +#define ENABLE_SEQUENTIALITY_TESTS 1 +#else +#define ENABLE_SEQUENTIALITY_TESTS 0 +#endif + #include "RZA1/cpu_specific.h" #include "RZA1/system/r_typedefs.h" #include "fault_handler.h" @@ -14,7 +20,7 @@ extern void freezeWithError(char const* errmsg); #ifdef __cplusplus } #endif - +#if defined(__arm__) #define FREEZE_WITH_ERROR(error) \ ({ \ uint32_t regLR = 0; \ @@ -24,7 +30,9 @@ extern void freezeWithError(char const* errmsg); fault_handler_print_freeze_pointers(0, 0, regLR, regSP); \ freezeWithError(error); \ }) - +#else +#define FREEZE_WITH_ERROR(error) ({ freezeWithError(error); }) +#endif #define TIMER_MIDI_GATE_OUTPUT 2 #define TIMER_SYSTEM_FAST 0 #define TIMER_SYSTEM_SLOW 4 diff --git a/src/deluge/dsp/delay/delay_buffer.cpp b/src/deluge/dsp/delay/delay_buffer.cpp index d0c0977fc8..adc113d791 100644 --- a/src/deluge/dsp/delay/delay_buffer.cpp +++ b/src/deluge/dsp/delay/delay_buffer.cpp @@ -133,8 +133,10 @@ void DelayBuffer::setupForRender(int32_t userDelayRate, DelayBufferSetup* setup) if (isResampling) { - setup->actualSpinRate = ((uint64_t)userDelayRate << 24) / nativeRate; // 1 is represented as 16777216 - setup->divideByRate = 0xFFFFFFFF / (setup->actualSpinRate >> 8); // 1 is represented as 65536 + setup->actualSpinRate = + (uint64_t)((double)((uint64_t)userDelayRate << 24) / (double)nativeRate); // 1 is represented as 16777216 + setup->divideByRate = + (uint32_t)((double)0xFFFFFFFF / (double)(setup->actualSpinRate >> 8)); // 1 is represented as 65536 // If buffer spinning slow if (setup->actualSpinRate < 16777216) { @@ -149,9 +151,10 @@ void DelayBuffer::setupForRender(int32_t userDelayRate, DelayBufferSetup* setup) // because more of that means more "triangle area", or more stuff written each time. //uint32_t delayWriteSizeAdjustment2 = (((uint32_t)delay.speed << 16) / (((uint32_t)(speedMultiple >> 2) * (uint32_t)(speedMultiple >> 2)) >> 11)); setup->writeSizeAdjustment = - (uint32_t)0xFFFFFFFF - / (setup->rateMultiple - * (timesSlowerRead + 1)); // Equivalent to one order of magnitude bigger than the above line + (uint32_t)((double)0xFFFFFFFF + / (double)(setup->rateMultiple + * (timesSlowerRead + + 1))); // Equivalent to one order of magnitude bigger than the above line } // If buffer spinning fast diff --git a/src/deluge/dsp/filter/filter.h b/src/deluge/dsp/filter/filter.h index cdaf8ee645..c5d82bed39 100644 --- a/src/deluge/dsp/filter/filter.h +++ b/src/deluge/dsp/filter/filter.h @@ -81,7 +81,7 @@ class Filter { //this is 1q31*1q16/(1q16+tan(f)/2) //tan(f) is q17 - divideBy1PlusTannedFrequency = (int64_t)ONE_Q31U * ONE_Q16 / (ONE_Q16 + (tannedFrequency >> 1)); + divideBy1PlusTannedFrequency = (q31_t)(288230376151711744.0 / (double)(ONE_Q16 + (tannedFrequency >> 1))); fc = multiply_32x32_rshift32_rounded(tannedFrequency, divideBy1PlusTannedFrequency) << 4; } q31_t fc; diff --git a/src/deluge/dsp/filter/hpladder.cpp b/src/deluge/dsp/filter/hpladder.cpp index a71623e82f..ad67280d77 100644 --- a/src/deluge/dsp/filter/hpladder.cpp +++ b/src/deluge/dsp/filter/hpladder.cpp @@ -43,7 +43,7 @@ q31_t HpLadderFilter::setConfig(q31_t hpfFrequency, q31_t hpfResonance, FilterMo // Extra feedback hpfProcessedResonance = multiply_32x32_rshift32(hpfProcessedResonance, extraFeedback) << 1; - hpfDivideByProcessedResonance = 2147483648u / (hpfProcessedResonance >> (23)); + hpfDivideByProcessedResonance = (q31_t)(2147483648.0 / (double)(hpfProcessedResonance >> (23))); int32_t moveabilityTimesProcessedResonance = multiply_32x32_rshift32(hpfProcessedResonanceUnaltered, fc); // 1 = 536870912 @@ -55,7 +55,7 @@ q31_t HpLadderFilter::setConfig(q31_t hpfFrequency, q31_t hpfResonance, FilterMo uint32_t toDivideBy = ((int32_t)268435456 - (moveabilityTimesProcessedResonance >> 1) + moveabilitySquaredTimesProcessedResonance); - divideByTotalMoveability = (int32_t)((uint64_t)hpfProcessedResonance * 67108864 / toDivideBy); + divideByTotalMoveability = (int32_t)((double)hpfProcessedResonance * 67108864.0 / (double)toDivideBy); hpfDoAntialiasing = (hpfProcessedResonance > 900000000); diff --git a/src/deluge/dsp/filter/lpladder.cpp b/src/deluge/dsp/filter/lpladder.cpp index 685566409a..372d510e5f 100644 --- a/src/deluge/dsp/filter/lpladder.cpp +++ b/src/deluge/dsp/filter/lpladder.cpp @@ -141,7 +141,7 @@ q31_t LpLadderFilter::setConfig(q31_t lpfFrequency, q31_t lpfResonance, FilterMo moveability, multiply_32x32_rshift32_rounded( moveability, multiply_32x32_rshift32_rounded( moveability, processedResonance))))); // 1 represented as 67108864 - divideByTotalMoveabilityAndProcessedResonance = (int64_t)67108864 * 1073741824 / onePlusThing; + divideByTotalMoveabilityAndProcessedResonance = (q31_t)(72057594037927936.0 / (double)onePlusThing); } if (lpfMode != FilterMode::TRANSISTOR_24DB_DRIVE) { // Cold transistor ladder only diff --git a/src/deluge/gui/ui/sound_editor.cpp b/src/deluge/gui/ui/sound_editor.cpp index b9eb48c407..fc753b92ce 100644 --- a/src/deluge/gui/ui/sound_editor.cpp +++ b/src/deluge/gui/ui/sound_editor.cpp @@ -432,6 +432,7 @@ void SoundEditor::exitCompletely() { } bool SoundEditor::findPatchedParam(int32_t paramLookingFor, int32_t* xout, int32_t* yout) { + bool found = false; for (int32_t x = 0; x < 15; x++) { for (int32_t y = 0; y < kDisplayHeight; y++) { if (paramShortcutsForSounds[x][y] && paramShortcutsForSounds[x][y] != comingSoonMenu @@ -439,11 +440,15 @@ bool SoundEditor::findPatchedParam(int32_t paramLookingFor, int32_t* xout, int32 *xout = x; *yout = y; - return true; + + if ((x & 1) == currentSourceIndex) { + //check we're on the corretc index + return true; + } } } } - return false; + return found; } void SoundEditor::updateSourceBlinks(MenuItem* currentItem) { diff --git a/src/deluge/gui/views/instrument_clip_view.cpp b/src/deluge/gui/views/instrument_clip_view.cpp index c489cedda1..87b2f8d065 100644 --- a/src/deluge/gui/views/instrument_clip_view.cpp +++ b/src/deluge/gui/views/instrument_clip_view.cpp @@ -5329,7 +5329,7 @@ void InstrumentClipView::editNumEuclideanEvents(ModelStackWithNoteRow* modelStac // Swap the new temporary note data into the permanent place noteRow->notes.swapStateWith(&newNotes); -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS noteRow->notes.testSequentiality("E376"); #endif } diff --git a/src/deluge/memory/cache_manager.cpp b/src/deluge/memory/cache_manager.cpp index 8380c85718..aed961342d 100644 --- a/src/deluge/memory/cache_manager.cpp +++ b/src/deluge/memory/cache_manager.cpp @@ -150,6 +150,7 @@ uint32_t CacheManager::ReclaimMemory(MemoryRegion& region, int32_t totalSizeNeed spaceSize += result.amountsExtended[0] + result.amountsExtended[1]; Debug::println("stole and grabbed neighbouring stuff too..........."); + AudioEngine::bypassCulling = true; // Paul: We don't want our samples to drop out because of this maneuver stolen = true; break; } diff --git a/src/deluge/model/clip/audio_clip.cpp b/src/deluge/model/clip/audio_clip.cpp index 8b0b99d1d7..1bc58f0312 100644 --- a/src/deluge/model/clip/audio_clip.cpp +++ b/src/deluge/model/clip/audio_clip.cpp @@ -533,7 +533,8 @@ void AudioClip::render(ModelStackWithTimelineCounter* modelStack, int32_t* outpu // To stop things getting insane, limit to 32x speed //if ((sampleLengthInSamples >> 5) > clipLengthInSamples) return false; - uint64_t requiredSpeedAdjustment = ((uint64_t)sampleLengthInSamples << 24) / clipLengthInSamples; + uint64_t requiredSpeedAdjustment = + (uint64_t)(((double)((uint64_t)sampleLengthInSamples << 24)) / (double)clipLengthInSamples); // If we're squishing time... if (sampleControls.pitchAndSpeedAreIndependent) { diff --git a/src/deluge/model/clip/instrument_clip.cpp b/src/deluge/model/clip/instrument_clip.cpp index a48439b7c8..3cf5988c3a 100644 --- a/src/deluge/model/clip/instrument_clip.cpp +++ b/src/deluge/model/clip/instrument_clip.cpp @@ -4385,7 +4385,7 @@ void InstrumentClip::recordNoteOn(ModelStackWithNoteRow* modelStack, int32_t vel else if (reversed) { doHomogenize: -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS param->nodes.testSequentiality( "E442"); // drbourbon got, when check was inside homogenizeRegion(). Now trying to work out where that came from. March 2022. #endif diff --git a/src/deluge/model/global_effectable/global_effectable_for_clip.cpp b/src/deluge/model/global_effectable/global_effectable_for_clip.cpp index 4b7afcc523..c1fdd75434 100644 --- a/src/deluge/model/global_effectable/global_effectable_for_clip.cpp +++ b/src/deluge/model/global_effectable/global_effectable_for_clip.cpp @@ -178,7 +178,8 @@ void GlobalEffectableForClip::renderOutput(ModelStackWithTimelineCounter* modelS &delayWorkingState, analogDelaySaturationAmount); processStutter(globalEffectableBuffer, numSamples, paramManagerForClip); - int32_t postReverbSendVolumeIncrement = (int32_t)(postReverbVolume - postReverbVolumeLastTime) / numSamples; + int32_t postReverbSendVolumeIncrement = + (int32_t)((double)(postReverbVolume - postReverbVolumeLastTime) / (double)numSamples); processReverbSendAndVolume(globalEffectableBuffer, numSamples, reverbBuffer, volumePostFX, postReverbVolumeLastTime, reverbSendAmount, pan, true, diff --git a/src/deluge/model/note/note_row.cpp b/src/deluge/model/note/note_row.cpp index 839bbe5c6c..a92fdb9658 100644 --- a/src/deluge/model/note/note_row.cpp +++ b/src/deluge/model/note/note_row.cpp @@ -504,7 +504,7 @@ int32_t NoteRow::addCorrespondingNotes(int32_t targetPos, int32_t newNotesLength // Swap the new temporary note data into the permanent place notes.swapStateWith(&newNotes); -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS notes.testSequentiality("E318"); #endif @@ -810,7 +810,7 @@ int32_t NoteRow::clearArea(int32_t areaStart, int32_t areaWidth, ModelStackWithN // Swap the new temporary note data into the permanent place notes.swapStateWith(&newNotes); -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS notes.testSequentiality("E319"); #endif @@ -1118,7 +1118,7 @@ int32_t NoteRow::editNoteRepeatAcrossAllScreens(int32_t editPos, int32_t squareW // Swap the new temporary note data into the permanent place notes.swapStateWith(&newNotes); -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS notes.testSequentiality("E328"); #endif @@ -1413,7 +1413,7 @@ int32_t NoteRow::nudgeNotesAcrossAllScreens(int32_t editPos, ModelStackWithNoteR // Swap the new temporary note data into the permanent place notes.swapStateWith(&newNotes); -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS notes.testSequentiality("E327"); #endif diff --git a/src/deluge/model/sample/sample_playback_guide.cpp b/src/deluge/model/sample/sample_playback_guide.cpp index 24d2d368a9..ba49679e5d 100644 --- a/src/deluge/model/sample/sample_playback_guide.cpp +++ b/src/deluge/model/sample/sample_playback_guide.cpp @@ -102,10 +102,10 @@ uint64_t SamplePlaybackGuide::getSyncedNumSamplesIn() { } // If following external clock, that could happen // TODO: is that still necessary? - return (uint64_t)(lengthInSamples * currentTickWithinSample - + (uint64_t)timeSinceLastInternalTick * lengthInSamples / timePerInternalTick - + (sequenceSyncLengthTicks >> 1)) // Rounding - / sequenceSyncLengthTicks; + return (uint64_t)(((double)(lengthInSamples * currentTickWithinSample) + + (double)timeSinceLastInternalTick * (double)lengthInSamples / (double)timePerInternalTick + + (double)(sequenceSyncLengthTicks >> 1)) // Rounding + / (double)sequenceSyncLengthTicks); } int32_t SamplePlaybackGuide::getNumSamplesLaggingBehindSync(VoiceSample* voiceSample) { diff --git a/src/deluge/modulation/automation/auto_param.cpp b/src/deluge/modulation/automation/auto_param.cpp index 4c41e9352c..a7124afa83 100644 --- a/src/deluge/modulation/automation/auto_param.cpp +++ b/src/deluge/modulation/automation/auto_param.cpp @@ -204,7 +204,7 @@ void AutoParam::setCurrentValueInResponseToUserInput(int32_t value, ModelStackWi bool shouldInterpolateLeft = reversed || shouldInterpolateRegionStart; -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS // drbourbon got, when check was inside homogenizeRegion(). Now trying to work out where that came from. // March 2022. nodes.testSequentiality("E435"); @@ -249,7 +249,7 @@ void AutoParam::setCurrentValueInResponseToUserInput(int32_t value, ModelStackWi skipThat : {} } -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS nodes.testSequentiality("ffff"); #endif @@ -688,7 +688,7 @@ int32_t AutoParam::processCurrentPos(ModelStackWithAutoParam const* modelStack, nextNodeInOurDirection = nodes.getElement(iRight); } -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS nodes.testSequentiality("eeee"); #endif } @@ -955,7 +955,7 @@ void AutoParam::setValueForRegion(uint32_t pos, uint32_t length, int32_t value, // Or, normal case else { -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS // drbourbon got, when check was inside homogenizeRegion(). Now trying to work out where that came from. // March 2022. Sven got, oddly while editing note velocity. Then again by "Adding some snares while playing". nodes.testSequentiality("E441"); @@ -1017,7 +1017,11 @@ int32_t AutoParam::homogenizeRegion(ModelStackWithAutoParam const* modelStack, i if (startPos < 0) { FREEZE_WITH_ERROR("E437"); } - // nodes.testSequentiality("E435"); // drbourbon got! March 2022. Now moved check to each caller. + + //#if ENABLE_SEQUENTIALITY_TESTS + // // nodes.testSequentiality("E435"); // drbourbon got! March 2022. Now moved check to each caller. + //#endif + if (nodes.getNumElements() && nodes.getFirst()->pos < 0) { FREEZE_WITH_ERROR("E436"); } @@ -1211,9 +1215,11 @@ int32_t AutoParam::homogenizeRegion(ModelStackWithAutoParam const* modelStack, i edgeIndexes[REGION_EDGE_LEFT] -= edgeIndexes[REGION_EDGE_RIGHT]; } -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS nodes.testSequentiality( "E433"); // Was "GGGG". Leo got. Sven got. (Probably now solved). (Nope, Michael got on V4.1.0-alpha10 (OLED)!) +#endif +#if ALPHA_OR_BETA_VERSION if (nodes.getNumElements()) { ParamNode* rightmostNode = nodes.getElement(nodes.getNumElements() - 1); if (rightmostNode->pos >= effectiveLength) { diff --git a/src/deluge/processing/audio_output.cpp b/src/deluge/processing/audio_output.cpp index a781e37094..b5211772e5 100644 --- a/src/deluge/processing/audio_output.cpp +++ b/src/deluge/processing/audio_output.cpp @@ -220,7 +220,7 @@ bool AudioOutput::renderGlobalEffectableForClip(ModelStackWithTimelineCounter* m inputChannelNow = AudioInputChannel::NONE; // 0 means combine channels } - int32_t amplitudeIncrement = (amplitudeAtEnd - amplitudeAtStart) / numSamples; + int32_t amplitudeIncrement = (int32_t)((double)(amplitudeAtEnd - amplitudeAtStart) / (double)numSamples); int32_t amplitudeNow = amplitudeAtStart; do { diff --git a/src/deluge/processing/sound/sound.cpp b/src/deluge/processing/sound/sound.cpp index 8cdee66e5e..b19627fa0f 100644 --- a/src/deluge/processing/sound/sound.cpp +++ b/src/deluge/processing/sound/sound.cpp @@ -2255,7 +2255,8 @@ void Sound::render(ModelStackWithThreeMainThings* modelStack, StereoSample* outp &postFXVolume, paramManager, 8); processStutter((StereoSample*)soundBuffer, numSamples, paramManager); - int32_t postReverbSendVolumeIncrement = (int32_t)(postReverbVolume - postReverbVolumeLastTime) / numSamples; + int32_t postReverbSendVolumeIncrement = + (int32_t)((double)(postReverbVolume - postReverbVolumeLastTime) / (double)numSamples); processReverbSendAndVolume((StereoSample*)soundBuffer, numSamples, reverbBuffer, postFXVolume, postReverbVolumeLastTime, reverbSendAmount, 0, true, postReverbSendVolumeIncrement); diff --git a/src/deluge/util/container/array/ordered_resizeable_array.cpp b/src/deluge/util/container/array/ordered_resizeable_array.cpp index ca7bab72dd..6156895274 100644 --- a/src/deluge/util/container/array/ordered_resizeable_array.cpp +++ b/src/deluge/util/container/array/ordered_resizeable_array.cpp @@ -260,10 +260,7 @@ void OrderedResizeableArray::deleteAtKey(int32_t key) { } void OrderedResizeableArray::testSequentiality(char const* errorCode) { - if (!ALPHA_OR_BETA_VERSION) { - return; - } - +#if ENABLE_SEQUENTIALITY_TESTS int32_t lastKey = -2147483648; for (int32_t i = 0; i < getNumElements(); i++) { int32_t key = getKeyAtIndex(i); @@ -273,6 +270,7 @@ void OrderedResizeableArray::testSequentiality(char const* errorCode) { lastKey = key; } +#endif } #define TEST_SEARCH_MULTIPLE_NUM_ITEMS 50000 @@ -624,7 +622,7 @@ void OrderedResizeableArrayWith32bitKey::shiftHorizontal(int32_t shiftAmount, in } } -#if ALPHA_OR_BETA_VERSION +#if ENABLE_SEQUENTIALITY_TESTS testSequentiality("E378"); #endif } diff --git a/src/deluge/util/container/array/ordered_resizeable_array_with_multi_word_key.cpp b/src/deluge/util/container/array/ordered_resizeable_array_with_multi_word_key.cpp index 7369862355..999c170ef9 100644 --- a/src/deluge/util/container/array/ordered_resizeable_array_with_multi_word_key.cpp +++ b/src/deluge/util/container/array/ordered_resizeable_array_with_multi_word_key.cpp @@ -121,10 +121,7 @@ bool OrderedResizeableArrayWithMultiWordKey::deleteAtKeyMultiWord(uint32_t* __re } void OrderedResizeableArrayWithMultiWordKey::testSequentiality(char const* errorCode) { - if (!ALPHA_OR_BETA_VERSION) { - return; - } - +#if ENABLE_SEQUENTIALITY_TESTS for (int32_t i = 1; i < getNumElements(); i++) { uint32_t* __restrict__ wordsHere = (uint32_t*)getElementAddress(i); uint32_t* __restrict__ lastWords = (uint32_t*)getElementAddress(i - 1); @@ -144,4 +141,5 @@ void OrderedResizeableArrayWithMultiWordKey::testSequentiality(char const* error } } } +#endif } diff --git a/tests/memory_tests.cpp b/tests/memory_tests.cpp index c42627f066..ba23159a56 100644 --- a/tests/memory_tests.cpp +++ b/tests/memory_tests.cpp @@ -9,6 +9,7 @@ #include #define NUM_TEST_ALLOCATIONS 1024 #define MEM_SIZE 10000000 + namespace { uint32_t vtableAddress; // will hold address of the stealable test vtable uint32_t nSteals; //to count steals @@ -305,7 +306,7 @@ TEST(MemoryAllocation, stealableAllocations) { void* testAllocations[NUM_TEST_ALLOCATIONS]; uint32_t actualSize; - mock().disable(); //disable mocking since number of steals is unpredictable + mock().expectNCalls(720, "steal"); for (int i = 0; i < NUM_TEST_ALLOCATIONS; i += 1) { uint32_t size = sizes[2]; if (i % 10 == 0) { @@ -327,6 +328,6 @@ TEST(MemoryAllocation, stealableAllocations) { std::cout << "stealable efficiency: " << efficiency << std::endl; //current efficiency is .994 CHECK(efficiency > 0.994); - mock().enable(); + mock().checkExpectations(); }; } // namespace diff --git a/tests/mocks/mock_display.cpp b/tests/mocks/mock_display.cpp index 6666208991..9a5895d90e 100644 --- a/tests/mocks/mock_display.cpp +++ b/tests/mocks/mock_display.cpp @@ -54,5 +54,13 @@ class MockDisplay : public deluge::hid::Display { bool have7SEG() { return false; } }; +extern "C" void freezeWithError(char const* error) { + display->freezeWithError(error); +} + +extern "C" void displayPopup(char const* text) { + display->displayPopup(text); +} + MockDisplay mockdisplay; deluge::hid::Display* display = &mockdisplay; diff --git a/tests/mocks/version.h b/tests/mocks/version.h new file mode 100644 index 0000000000..e8bd9cc630 --- /dev/null +++ b/tests/mocks/version.h @@ -0,0 +1,36 @@ +//mock up the version.h that would be made by cmake in the main build + +#pragma once + +#ifdef __cplusplus +#include +#include + +struct SemVer { + uint8_t major; + uint8_t minor; + uint8_t patch; + + auto operator<=>(const SemVer&) const = default; +}; + +// clang-format off +constexpr SemVer kCommunityFirmwareVersion { + 0, + 0, + 0, +}; +//clang-format on + +constexpr char const* kFirmwareVersionString = "TESTS"; + +#else + +#define FIRMWARE_VERSION_MAJOR 0 +#define FIRMWARE_VERSION_MINOR 0 +#define FIRMWARE_VERSION_PATCH 0 + +#define FIRMWARE_VERSION_STRING "TESTS" +#define FIRMWARE_COMMIT_SHORT "0000" + +#endif