33dff96a20
This commit contains changes required for MuseScore to compile under MSVC with no warnings. MuseScore is being compiled with the /W4 setting (warning level 4), which is similar to -wall -wextra on clang. This generates lots of warnings on MSVC, mainly for non-standard constructs and for constructs which might be bugs or might lead to bugs. Most warnings are in the following categories: - Name hiding: a variable hides a variable with the same name on a larger scope (or a field, or a function parameter). This can easily lead to bugs, and it is a best practice to avoid hiding variable names (see recommendation ES.12 in the C++ Core Guidelines by Stroustrop & Sutter (http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-reuse : ES.12: Do not reuse names in nested scopes) - Narrowing conversion: a numeric conversion results in loss of significant digits (for example, double -> float). The general recommendation is to use a cast to indicate this is designed behaviour. - Unreachable code: in several instances, there is unreachable code. The unreachable code is commented out. - (Potentially) uninitialized local variable. Just initialized the vars. - foreach(,) -> for(:): this does not generate a warning per-se (only a few of these generate warnings due to name hiding), but changed in keeping with "MuseScore Coding Rules" (https://musescore.org/en/handbook/musescore-coding-rules#Loops), which tells explicitly "Use C++11's "for" instead of Qt's "foreach":" ... "If you happen to be fixing some code and see a "foreach", please change that loop into a "for"." Most changes are in the categories indicated above. The next listing shows detailed changes for files which are *not* of the aforementioned types. - all.h: Disable warning C4127 (conditional expression is constant - generated in Qt header file qvector.h) - awl/aslider.h: unreachable code. - awl/knob.cpp: name hiding - awl/mslider.cpp: name hiding - awl/slider.cpp: name hiding - bww2mxml/parser.cpp: name hiding - effects/compressor/compressor.cpp: narrowing conversion - effects/zita1/zitagui.cpp: name hiding - fluid/fluid.cpp: foreach replacement. Name hiding. - fluid/mod.cpp: name hiding. - fluid/sfont.cpp: foreach replacement. Name hiding. Initialize vars. - fluid/voice.cpp: Name hiding. - libmscore/accidental.cpp: Name hiding. - libmscore/ambitus.cpp: Initialize vars. - libmscore/barline.cpp: Name hiding. Unreachable code. - libmscore/beam.cpp: Name hiding. - libmscore/chordrest.cpp: Unreachable code. - libmscore/scorefile.cpp: Name hiding. - manual/genManual.cpp: Name hiding. foreach replacement. - midi/midifile.cpp: Name hiding. Unreachable code. - omr/importpdf.cpp: Name hiding. foreach replacement. - omr/omr.cpp: Name hiding. foreach replacement. - omr/omrpage.cpp: Name hiding. foreach replacement. - omr/omrview.cpp: Name hiding. foreach replacement. - synthesizer/event.cpp: Unreachable code. - zerberus\channel.cpp: Narrowing conversion. - zerberus\instrument.cpp: Name hiding. - zerberus\sfz.cpp: Name hiding. - zerberus\voice.h: Suppress warning C4201: "nonstandard extension used: nameless struct/union" - zerberus\zerberus.cpp: Name hiding. Unreferenced parameter. - zerberus\zerberusgui.cpp: Name hiding.
185 lines
5.3 KiB
C++
185 lines
5.3 KiB
C++
//=============================================================================
|
|
// Zerberus
|
|
// Zample player
|
|
//
|
|
// Copyright (C) 2013 Werner Schweer
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 2
|
|
// as published by the Free Software Foundation and appearing in
|
|
// the file LICENCE.GPL
|
|
//=============================================================================
|
|
|
|
#ifndef __MVOICE_H__
|
|
#define __MVOICE_H__
|
|
|
|
#include <cstdint>
|
|
#include <math.h>
|
|
#include "filter.h"
|
|
|
|
// Disable warning C4201: nonstandard extension used: nameless struct/union in VS2017
|
|
#if (defined (_MSCVER) || defined (_MSC_VER))
|
|
#pragma warning ( disable: 4201)
|
|
#endif
|
|
|
|
class Channel;
|
|
struct Zone;
|
|
class Sample;
|
|
class Zerberus;
|
|
|
|
enum class LoopMode : char;
|
|
enum class OffMode : char;
|
|
enum class Trigger : char;
|
|
|
|
static const int EG_SIZE = 256;
|
|
|
|
//---------------------------------------------------------
|
|
// Envelope
|
|
//---------------------------------------------------------
|
|
|
|
struct Envelope {
|
|
static float egPow[EG_SIZE];
|
|
static float egLin[EG_SIZE];
|
|
|
|
int steps, count;
|
|
bool constant = false;
|
|
float offset = 0.0;
|
|
float max = 1.0;
|
|
float val;
|
|
float* table;
|
|
|
|
void setTable(float* f) { table = f; }
|
|
bool step() {
|
|
if (count) {
|
|
--count;
|
|
if (!constant)
|
|
val = table[EG_SIZE * count/steps]*(max-offset)+offset;
|
|
return false;
|
|
}
|
|
else
|
|
return true;
|
|
}
|
|
void setTime(float ms, int sampleRate);
|
|
void setConstant(float v) { constant = true; val = v; }
|
|
void setVariable() { constant = false; }
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Phase
|
|
// Playing pointer for voice playback
|
|
//
|
|
// When a sample is played back at a different pitch, the playing pointer
|
|
// in the source sample will not advance exactly one sample per output sample.
|
|
//
|
|
// This playing pointer is implemented using Phase.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
struct Phase {
|
|
union {
|
|
int64_t data;
|
|
struct {
|
|
uint8_t _fract;
|
|
};
|
|
};
|
|
|
|
void operator+=(const Phase& p) { data += p.data; }
|
|
void set(int b) { data = b * 256; }
|
|
void set(double b) { data = b * 256.0; }
|
|
void setIndex(int b) { data = b * 256 + _fract; }
|
|
int index() const { return data >> 8; }
|
|
unsigned fract() const { return _fract; }
|
|
|
|
Phase() {}
|
|
Phase(int64_t v) : data(v) {}
|
|
};
|
|
|
|
enum class VoiceState : char {
|
|
OFF,
|
|
ATTACK,
|
|
PLAYING,
|
|
SUSTAINED,
|
|
STOP
|
|
};
|
|
|
|
enum V1Envelopes : int {
|
|
DELAY,
|
|
ATTACK,
|
|
HOLD,
|
|
DECAY,
|
|
SUSTAIN,
|
|
RELEASE,
|
|
COUNT
|
|
};
|
|
|
|
//---------------------------------------------------------
|
|
// Voice
|
|
//---------------------------------------------------------
|
|
|
|
class Voice {
|
|
Voice* _next;
|
|
Zerberus* _zerberus;
|
|
|
|
VoiceState _state = VoiceState::OFF;
|
|
Channel* _channel;
|
|
int _key;
|
|
int _velocity;
|
|
int audioChan;
|
|
|
|
short* data;
|
|
long long eidx;
|
|
LoopMode _loopMode;
|
|
OffMode _offMode;
|
|
int _offBy;
|
|
long long _loopStart;
|
|
long long _loopEnd;
|
|
bool _looping;
|
|
int _samplesSinceStart;
|
|
|
|
float gain;
|
|
|
|
Phase phase, phaseIncr;
|
|
|
|
ZFilter filter;
|
|
|
|
int currentEnvelope;
|
|
Envelope envelopes[V1Envelopes::COUNT];
|
|
|
|
Trigger trigger;
|
|
|
|
const Zone* z;
|
|
|
|
public:
|
|
Voice(Zerberus*);
|
|
Voice* next() const { return _next; }
|
|
void setNext(Voice* v) { _next = v; }
|
|
|
|
void start(Channel* channel, int key, int velo, const Zone*, double durSinceNoteOn);
|
|
void updateEnvelopes();
|
|
void process(int frames, float*);
|
|
void updateLoop();
|
|
short getData(long long pos);
|
|
|
|
Channel* channel() const { return _channel; }
|
|
int key() const { return _key; }
|
|
int velocity() const { return _velocity; }
|
|
|
|
bool isPlaying() const { return _state == VoiceState::PLAYING || _state == VoiceState::ATTACK; }
|
|
bool isSustained() const { return _state == VoiceState::SUSTAINED; }
|
|
bool isOff() const { return _state == VoiceState::OFF; }
|
|
bool isStopped() const { return _state == VoiceState::STOP; }
|
|
void stop() { envelopes[currentEnvelope].step(); envelopes[V1Envelopes::RELEASE].max = envelopes[currentEnvelope].val; currentEnvelope = V1Envelopes::RELEASE; _state = VoiceState::STOP; }
|
|
void stop(float time);
|
|
void sustained() { _state = VoiceState::SUSTAINED; }
|
|
void off() { _state = VoiceState::OFF; }
|
|
const char* state() const;
|
|
LoopMode loopMode() const { return _loopMode; }
|
|
int getSamplesSinceStart() { return _samplesSinceStart; }
|
|
float getGain() { return gain; }
|
|
|
|
OffMode offMode() const { return _offMode; }
|
|
int offBy() const { return _offBy; }
|
|
static void init();
|
|
};
|
|
|
|
#endif
|
|
|