gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

microq.h (4747B)


      1 #pragma once
      2 
      3 #include <atomic>
      4 #include <memory>
      5 #include <mutex>
      6 #include <string>
      7 #include <thread>
      8 #include <vector>
      9 
     10 #include "buttons.h"
     11 #include "leds.h"
     12 #include "mqtypes.h"
     13 
     14 namespace synthLib
     15 {
     16 	struct SMidiEvent;
     17 }
     18 
     19 namespace mqLib
     20 {
     21 	class Hardware;
     22 
     23 	class MicroQ
     24 	{
     25 	public:
     26 		MicroQ(BootMode _bootMode = BootMode::Default, const std::vector<uint8_t>& _romData = {}, const std::string& _romName = {});
     27 		~MicroQ();
     28 
     29 		// returns true if the instance is valid, false if the initialization failed
     30 		bool isValid() const;
     31 
     32 		// Process a block of audio data. Be sure to pass two channels for the inputs and six channels for the outputs
     33 		// _frames means the number of samples per channel
     34 		// _latency additional latency in samples that will be added to allow asynchronous processing
     35 		void process(const float** _inputs, float** _outputs, uint32_t _frames, uint32_t _latency = 0);
     36 
     37 		// Process a block of audio data. Data conversion is not performed, this allows to access raw DSP data
     38 		// The used input and output buffers can be queried below
     39 		void process(uint32_t _frames, uint32_t _latency = 0);
     40 
     41 		// Retrieve the DSP audio input. Two channels, 24 bits. Only the 24 LSBs of each 32 bit word are used
     42 		TAudioInputs& getAudioInputs();
     43 
     44 		// Retrieve the DSP audio output. Two channels, 24 bits. Only the 24 LSBs of each 32 bit word are used
     45 		TAudioOutputs& getAudioOutputs();
     46 
     47 		// send midi to the midi input of the device
     48 		void sendMidiEvent(const synthLib::SMidiEvent& _ev);
     49 
     50 		// Receive midi data that the device generated during the last call of process().
     51 		// Note that any midi output data not queried between two calls of process() is lost
     52 		void receiveMidi(std::vector<uint8_t>& _buffer);
     53 
     54 		// Get the status of one of the front panel buttons
     55 		bool getButton(Buttons::ButtonType _button);
     56 
     57 		// Set the status of one of the front panel buttons
     58 		void setButton(Buttons::ButtonType _button, bool _pressed);
     59 
     60 		// retrieve the current value of a front panel encoder
     61 		uint8_t getEncoder(Buttons::Encoders _encoder);
     62 
     63 		// Rotate an encoder on the front panel by a specific amount
     64 		void rotateEncoder(Buttons::Encoders _encoder, int _amount);
     65 
     66 		// Return the state of a front panel LED. true = lit
     67 		bool getLedState(Leds::Led _led);
     68 
     69 		// Read the current LCD content. Returns 40 characters that represent two lines with 20 characters each
     70 		// If the returned character is less than 8, it is a custom character with predefined pixel data
     71 		// You may query the pixel data via readCustomLCDCharacter below
     72 		void readLCD(std::array<char, 40>& _data);
     73 
     74 		// Read a custom LCD character. _characterIndex needs to be < 8
     75 		// A custom character has the dimensions 5*8 pixels
     76 		// The _data argument receives one byte per row, with the topmost row at index 0, the bottommost row at index 7
     77 		// Pixels per row are stored in the five LSBs of each byte, with the leftmost pixel at bit 4, the rightmost pixel at bit 0
     78 		// A set bit indicates a set pixel.
     79 		// As an example, the character 'P', encoded as a custom character, would look like this:
     80 		//
     81 		// bit       7  6  5  4  3  2  1  0
     82 		// byte 0             *  *  *  *  -     top
     83 		// byte 1             *  -  -  -  *
     84 		// byte 2             *  -  -  -  *
     85 		// byte 3             *  *  *  *  -
     86 		// byte 4             *  -  -  -  -
     87 		// byte 5             *  -  -  -  -
     88 		// byte 6             *  -  -  -  -
     89 		// byte 7             *  -  -  -  -     bottom
     90 		//
     91 		bool readCustomLCDCharacter(std::array<uint8_t, 8>& _data, uint32_t _characterIndex);
     92 
     93 		// Dirty flags indicate that the front panel of the device has changed. To be retrieved via getDirtyFlags()
     94 		enum class DirtyFlags : uint32_t
     95 		{
     96 			None		= 0,
     97 			Leds		= 0x01,	// one or more LEDs changed its state
     98 			Lcd			= 0x02,	// the LCD has been refreshed and should be repainted
     99 			LcdCgRam	= 0x04,	// the LCD CG RAM has been modified, custom characters need to be repainted
    100 		};
    101 
    102 		// Retrieve dirty flags for the front panel. See enum DirtyFlags for a description
    103 		// Dirty flags are sticky but are reset upon calling this function
    104 		DirtyFlags getDirtyFlags();
    105 
    106 		// Gain access to the hardware implementation, intended for advanced use. Usually not required
    107 		Hardware* getHardware();
    108 
    109 		// returns after the device has booted and is ready to receive midi commands
    110 		bool isBootCompleted() const;
    111 
    112 	private:
    113 		void internalProcess(uint32_t _frames, uint32_t _latency);
    114 		void onLedsChanged();
    115 		void onLcdChanged();
    116 		void onLcdCgRamChanged();
    117 
    118 		void processUcThread() const;
    119 
    120 		std::unique_ptr<Hardware> m_hw;
    121 
    122 		std::mutex m_mutex;
    123 
    124 		std::vector<uint8_t> m_midiOutBuffer;
    125 
    126 		std::unique_ptr<std::thread> m_ucThread;
    127 		bool m_destroy = false;
    128 		std::atomic<uint32_t> m_dirtyFlags = 0;
    129 	};
    130 }