diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..fd268a014 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,37 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,abseil-*,bugprone-*,performance-*,-abseil-no-internal-dependencies' +WarningsAsErrors: 'clang-diagnostic-*,clang-analyzer-*,abseil-*,bugprone-*,performance-*' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: file +User: paul +CheckOptions: + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: '0' + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: '1' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: '1' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: 'NULL' +... diff --git a/.travis.yml b/.travis.yml index 47a733c5a..16cd21929 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,23 @@ language: cpp jobs: + - os: linux + stage: "Tests" + name: "clang-tidy checks" + dist: bionic + addons: + apt: + packages: + - clang-tidy + - libsndfile-dev + before_install: + - true + install: + - true + script: + - scripts/run_clang_tidy.sh + after_success: + - true - os: linux stage: "Build" name: "Windows mingw32" diff --git a/scripts/run_clang_tidy.sh b/scripts/run_clang_tidy.sh new file mode 100755 index 000000000..e660173b6 --- /dev/null +++ b/scripts/run_clang_tidy.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +clang-tidy \ + src/sfizz/ADSREnvelope.cpp \ + src/sfizz/Effects.cpp \ + src/sfizz/EQPool.cpp \ + src/sfizz/EventEnvelopes.cpp \ + src/sfizz/FilePool.cpp \ + src/sfizz/FilterPool.cpp \ + src/sfizz/FloatEnvelopes.cpp \ + src/sfizz/Logger.cpp \ + src/sfizz/MidiState.cpp \ + src/sfizz/Opcode.cpp \ + src/sfizz/Oversampler.cpp \ + src/sfizz/Parser.cpp \ + src/sfizz/sfizz.cpp \ + src/sfizz/Region.cpp \ + src/sfizz/SfzHelpers.cpp \ + src/sfizz/SIMDSSE.cpp \ + src/sfizz/Synth.cpp \ + src/sfizz/Voice.cpp \ + src/sfizz/effects/Lofi.cpp \ + src/sfizz/effects/Nothing.cpp \ + -- -Iexternal/abseil-cpp -Isrc/external -Isrc/external/pugixml/src -Isrc/sfizz -Isrc diff --git a/src/sfizz/ADSREnvelope.cpp b/src/sfizz/ADSREnvelope.cpp index c1fad38e0..e795d53f3 100644 --- a/src/sfizz/ADSREnvelope.cpp +++ b/src/sfizz/ADSREnvelope.cpp @@ -178,7 +178,8 @@ void ADSREnvelope::getBlock(absl::Span output) noexcept if (shouldRelease) { remainingSamples = static_cast(originalSpan.size()); - if (releaseDelay > remainingSamples) { + if (releaseDelay > remainingSamples) + { releaseDelay -= remainingSamples; return; } diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h index 2b734d919..4d01301c5 100644 --- a/src/sfizz/Defaults.h +++ b/src/sfizz/Defaults.h @@ -125,7 +125,7 @@ namespace Default constexpr Range rtDecayRange { 0.0f, 200.0f }; // Performance parameters: Filters - constexpr float numFilters { 2 }; + constexpr int numFilters { 2 }; constexpr float filterCutoff { 0 }; constexpr float filterResonance { 0 }; constexpr float filterGain { 0 }; @@ -147,7 +147,7 @@ namespace Default constexpr Range filterResonanceModRange { 0.0f, 96.0f }; // Performance parameters: EQ - constexpr float numEQs { 3 }; + constexpr int numEQs { 3 }; constexpr float eqBandwidth { 1.0f }; constexpr float eqBandwidthCC { 0.0f }; constexpr float eqFrequencyUnset { 0.0f }; diff --git a/src/sfizz/FilePool.cpp b/src/sfizz/FilePool.cpp index 894922658..a716d32b5 100644 --- a/src/sfizz/FilePool.cpp +++ b/src/sfizz/FilePool.cpp @@ -218,7 +218,7 @@ bool sfz::FilePool::preloadFile(const std::string& filename, uint32_t maxOffset) } else { preloadedFiles.insert_or_assign(filename, { readFromFile(sndFile, framesToLoad, oversamplingFactor), - static_cast(oversamplingFactor) * sndFile.samplerate() + static_cast(oversamplingFactor) * static_cast(sndFile.samplerate()) }); } diff --git a/src/sfizz/FilterPool.cpp b/src/sfizz/FilterPool.cpp index af56f3b6a..354486dfb 100644 --- a/src/sfizz/FilterPool.cpp +++ b/src/sfizz/FilterPool.cpp @@ -31,7 +31,7 @@ void sfz::FilterHolder::setup(const FilterDescription& description, unsigned num } const auto keytrack = description.keytrack * (noteNumber - description.keycenter); baseCutoff *= centsFactor(keytrack); - const auto veltrack = description.veltrack * normalizeVelocity(velocity); + const auto veltrack = static_cast(description.veltrack) * normalizeVelocity(velocity); baseCutoff *= centsFactor(veltrack); baseCutoff = Default::filterCutoffRange.clamp(baseCutoff); diff --git a/src/sfizz/Logger.cpp b/src/sfizz/Logger.cpp index 53bfa66bf..15b7fa860 100644 --- a/src/sfizz/Logger.cpp +++ b/src/sfizz/Logger.cpp @@ -98,12 +98,12 @@ sfz::Logger::~Logger() } -void sfz::Logger::logCallbackTime(CallbackBreakdown&& breakdown, int numVoices, size_t numSamples) +void sfz::Logger::logCallbackTime(const CallbackBreakdown& breakdown, int numVoices, size_t numSamples) { if (!loggingEnabled) return; - callbackTimeQueue.try_push({ std::move(breakdown), numVoices, numSamples }); + callbackTimeQueue.try_push({ breakdown, numVoices, numSamples }); } void sfz::Logger::logFileTime(std::chrono::duration waitDuration, std::chrono::duration loadDuration, uint32_t fileSize, absl::string_view filename) diff --git a/src/sfizz/Logger.h b/src/sfizz/Logger.h index 449c19d9d..d23cb618d 100644 --- a/src/sfizz/Logger.h +++ b/src/sfizz/Logger.h @@ -108,7 +108,7 @@ class Logger * @param numVoices The number of active voices * @param numSamples The number of samples in the callback */ - void logCallbackTime(CallbackBreakdown&& breakdown, int numVoices, size_t numSamples); + void logCallbackTime(const CallbackBreakdown& breakdown, int numVoices, size_t numSamples); /** * @brief Log a file loading and waiting duration diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 004b5fe91..ddf2a764d 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -250,7 +250,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("volume"): setValueFromOpcode(opcode, volume, Default::volumeRange); break; - case hash("gain_cc&"): [[fallthrough]]; + case hash("gain_cc&"): case hash("gain_oncc&"): [[fallthrough]]; case hash("volume_oncc&"): setCCPairFromOpcode(opcode, volumeCC, Default::volumeCCRange); @@ -395,8 +395,8 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, filters[filterIndex].resonance, Default::filterResonanceRange); } break; - case hash("cutoff_oncc&"): [[fallthrough]]; - case hash("cutoff_cc&"): [[fallthrough]]; + case hash("cutoff_oncc&"): + case hash("cutoff_cc&"): case hash("cutoff&_oncc&"): [[fallthrough]]; case hash("cutoff&_cc&"): { @@ -411,8 +411,8 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) ); } break; - case hash("resonance&_oncc&"): [[fallthrough]]; - case hash("resonance&_cc&"): [[fallthrough]]; + case hash("resonance&_oncc&"): + case hash("resonance&_cc&"): case hash("resonance_oncc&"): [[fallthrough]]; case hash("resonance_cc&"): { diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 100aef69f..738c524a3 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -567,7 +567,7 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept buffer.applyGain(db2mag(volume)); callbackBreakdown.dispatch = dispatchDuration; - resources.logger.logCallbackTime(std::move(callbackBreakdown), numActiveVoices, numFrames); + resources.logger.logCallbackTime(callbackBreakdown, numActiveVoices, numFrames); // Reset the dispatch counter dispatchDuration = Duration(0); @@ -938,7 +938,7 @@ void sfz::Synth::resetAllControllers(int delay) noexcept fs::file_time_type sfz::Synth::checkModificationTime() { auto returnedTime = modificationTime; - for (auto file: getIncludedFiles()) { + for (const auto& file: getIncludedFiles()) { const auto fileTime = fs::last_write_time(file); if (returnedTime < fileTime) returnedTime = fileTime; diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index df3e3c105..8f75c25c4 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -82,7 +82,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value pitchBendEnvelope.setFunction([region](float pitchValue){ const auto normalizedBend = normalizeBend(pitchValue); - const auto bendInCents = normalizedBend > 0.0f ? normalizedBend * region->bendUp : -normalizedBend * region->bendDown; + const auto bendInCents = normalizedBend > 0.0f ? normalizedBend * static_cast(region->bendUp) : -normalizedBend * static_cast(region->bendDown); return centsFactor(bendInCents); }); pitchBendEnvelope.reset(static_cast(resources.midiState.getPitchBend())); @@ -106,7 +106,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value sourcePosition = region->getOffset(); triggerDelay = delay; - initialDelay = delay + static_cast(region->getDelay() * sampleRate); + initialDelay = delay + static_cast(region->getDelay() * sampleRate); baseFrequency = midiNoteFrequency(number); bendStepFactor = centsFactor(region->bendStep); egEnvelope.reset(*region, resources.midiState, delay, value, sampleRate); diff --git a/src/sfizz/effects/Lofi.cpp b/src/sfizz/effects/Lofi.cpp index 1fcc33045..60b669498 100644 --- a/src/sfizz/effects/Lofi.cpp +++ b/src/sfizz/effects/Lofi.cpp @@ -132,7 +132,7 @@ namespace fx { for (uint32_t i = 0; i < nframes; ++i) { float x = in[i]; - float y = std::copysign((int)(0.5f + std::fabs(x * steps)), x) * invSteps; + float y = std::copysign((int)(0.5f + std::fabs(x * steps)), x) * invSteps; // NOLINT float y2x[2]; y2x[0] = (y != lastValue) ? (0.5f * (y + lastValue)) : y; @@ -150,7 +150,7 @@ namespace fx { /// void Lofi::Decim::init(double sampleRate) { - fSampleTime = 1.0 / sampleRate; + fSampleTime = 1.0f / static_cast(sampleRate); static constexpr double coefs2x[12] = { 0.036681502163648017, 0.13654762463195794, 0.27463175937945444, 0.42313861743656711, 0.56109869787919531, 0.67754004997416184, 0.76974183386322703, 0.83988962484963892, 0.89226081800387902, 0.9315419599631839, 0.96209454837808417, 0.98781637073289585 }; fDownsampler2x.set_coefs(coefs2x); @@ -192,7 +192,7 @@ namespace fx { phase += dt; float y = (phase > 1.0f) ? x : lastValue; - phase -= static_cast(phase); + phase -= static_cast(static_cast(phase)); float y2x[2]; y2x[0] = (y != lastValue) ? (0.5f * (y + lastValue)) : y;