MuseScore/zerberus/voice.h
Andres Fernandez de Prado 33dff96a20 This commit contains changes required for MuseScore to compile under MSVC with no warnings.
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.
2018-08-03 09:15:42 +02:00

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