sfizz/sources/Voice.h

114 lines
4.1 KiB
C
Raw Normal View History

2019-08-30 00:49:58 +02:00
// Copyright (c) 2019, Paul Ferrand
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2019-07-29 02:13:03 +02:00
#pragma once
2019-08-24 15:32:06 +02:00
#include "ADSREnvelope.h"
2019-08-23 01:27:39 +02:00
#include "Globals.h"
#include "Region.h"
2019-08-24 15:50:55 +02:00
#include "StereoBuffer.h"
#include "StereoSpan.h"
2019-08-29 11:48:38 +02:00
#include <absl/types/span.h>
#include <atomic>
2019-07-29 02:13:03 +02:00
2019-08-24 15:50:55 +02:00
namespace sfz {
class Voice {
2019-07-29 02:13:03 +02:00
public:
2019-08-24 15:32:06 +02:00
Voice() = delete;
2019-08-29 11:48:38 +02:00
Voice(const CCValueArray& ccState);
2019-08-24 15:50:55 +02:00
enum class TriggerType {
2019-08-24 15:32:06 +02:00
NoteOn,
NoteOff,
CC
};
2019-08-29 16:23:35 +02:00
void setSampleRate(float sampleRate) noexcept;
void setSamplesPerBlock(int samplesPerBlock) noexcept;
2019-08-29 11:48:38 +02:00
2019-08-29 16:23:35 +02:00
void startVoice(Region* region, int delay, int channel, int number, uint8_t value, TriggerType triggerType) noexcept;
2019-08-29 11:48:38 +02:00
2019-08-29 16:23:35 +02:00
void setFileData(std::unique_ptr<StereoBuffer<float>> file) noexcept;
void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity) noexcept;
void registerCC(int delay, int channel, int ccNumber, uint8_t ccValue) noexcept;
void registerPitchWheel(int delay, int channel, int pitch) noexcept;
void registerAftertouch(int delay, int channel, uint8_t aftertouch) noexcept;
void registerTempo(int delay, float secondsPerQuarter) noexcept;
2019-08-29 11:48:38 +02:00
bool checkOffGroup(int delay [[maybe_unused]], uint32_t group) noexcept;
2019-08-23 01:27:39 +02:00
2019-08-29 16:23:35 +02:00
void renderBlock(StereoSpan<float> buffer) noexcept;
2019-08-24 15:32:06 +02:00
2019-08-29 16:23:35 +02:00
bool isFree() const noexcept;
int getTriggerNumber() const noexcept;
int getTriggerChannel() const noexcept;
uint8_t getTriggerValue() const noexcept;
TriggerType getTriggerType() const noexcept;
2019-08-24 15:32:06 +02:00
2019-08-29 16:23:35 +02:00
void reset() noexcept;
void garbageCollect() noexcept;
2019-07-29 02:13:03 +02:00
private:
2019-08-29 16:23:35 +02:00
void fillWithData(StereoSpan<float> buffer) noexcept;
void fillWithGenerator(StereoSpan<float> buffer) noexcept;
void prepareEGEnvelope(int delay, uint8_t velocity) noexcept;
2019-08-29 11:48:38 +02:00
2019-08-25 14:26:20 +02:00
Region* region { nullptr };
2019-08-24 15:32:06 +02:00
2019-08-24 15:50:55 +02:00
enum class State {
2019-08-24 15:32:06 +02:00
idle,
playing,
release
};
2019-08-25 14:26:20 +02:00
State state { State::idle };
bool noteIsOff { false };
2019-08-23 01:27:39 +02:00
TriggerType triggerType;
int triggerNumber;
int triggerChannel;
uint8_t triggerValue;
2019-08-24 15:50:55 +02:00
float speedRatio { 1.0 };
float pitchRatio { 1.0 };
float baseGain { 1.0 };
float baseFrequency { 440.0 };
float phase { 0.0f };
2019-08-24 15:32:06 +02:00
2019-08-25 14:26:20 +02:00
uint32_t sourcePosition { 0 };
float floatPosition { 0.0f };
2019-08-25 14:26:20 +02:00
uint32_t initialDelay { 0 };
2019-08-24 15:32:06 +02:00
std::atomic<bool> dataReady { false };
std::unique_ptr<StereoBuffer<float>> fileData { nullptr };
2019-08-23 01:27:39 +02:00
2019-08-24 15:32:06 +02:00
Buffer<float> tempBuffer1;
Buffer<float> tempBuffer2;
Buffer<int> indexBuffer;
2019-08-24 15:50:55 +02:00
absl::Span<float> tempSpan1 { absl::MakeSpan(tempBuffer1) };
absl::Span<float> tempSpan2 { absl::MakeSpan(tempBuffer2) };
absl::Span<int> indexSpan { absl::MakeSpan(indexBuffer) };
2019-08-24 15:32:06 +02:00
2019-08-24 15:50:55 +02:00
int samplesPerBlock { config::defaultSamplesPerBlock };
double sampleRate { config::defaultSampleRate };
2019-08-24 15:32:06 +02:00
2019-08-24 15:50:55 +02:00
const CCValueArray& ccState;
2019-08-24 15:32:06 +02:00
ADSREnvelope<float> egEnvelope;
LEAK_DETECTOR(Voice);
2019-07-29 02:13:03 +02:00
};
2019-08-23 01:27:39 +02:00
2019-08-24 15:32:06 +02:00
} // namespace sfz