added playback cursor

This commit is contained in:
Igor Korsukov 2020-07-18 10:21:52 +02:00
parent 2287ebf6c3
commit 3e2e712ca7
9 changed files with 444 additions and 753 deletions

View file

@ -40,7 +40,8 @@ freely, subject to the following restrictions:
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h> // only needed for OutputDebugStringA, should be solved somehow.
#define SOLOUD_ASSERT(x) if (!(x)) { char temp[200]; sprintf(temp, "%s(%d): assert(%s) failed.\n", __FILE__, __LINE__, #x); OutputDebugStringA(temp); __debugbreak(); }
#define SOLOUD_ASSERT(x) if (!(x)) { char temp[200]; sprintf(temp, "%s(%d): assert(%s) failed.\n", __FILE__, __LINE__, \
#x); OutputDebugStringA(temp); __debugbreak(); }
#else
#include <assert.h> // assert
#define SOLOUD_ASSERT(x) assert(x)
@ -63,12 +64,12 @@ freely, subject to the following restrictions:
#define M_PI 3.14159265359
#endif
#if defined(_WIN32)||defined(_WIN64)
#if defined(_WIN32) || defined(_WIN64)
#define WINDOWS_VERSION
#endif
#if !defined(DISABLE_SIMD)
#if defined(__x86_64__) || defined( _M_X64 ) || defined( __i386 ) || defined( _M_IX86 )
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86)
#define SOLOUD_SSE_INTRINSICS
#endif
#endif
@ -100,47 +101,45 @@ freely, subject to the following restrictions:
// Typedefs have to be made before the includes, as the
// includes depend on them.
namespace SoLoud
namespace SoLoud {
class Soloud;
typedef void (* mutexCallFunction)(void* aMutexPtr);
typedef void (* soloudCallFunction)(Soloud* aSoloud);
typedef unsigned int result;
typedef unsigned int handle;
typedef double time;
}
namespace SoLoud {
// Class that handles aligned allocations to support vectorized operations
class AlignedFloatBuffer
{
class Soloud;
typedef void (*mutexCallFunction)(void *aMutexPtr);
typedef void (*soloudCallFunction)(Soloud *aSoloud);
typedef unsigned int result;
typedef unsigned int handle;
typedef double time;
public:
float* mData; // aligned pointer
unsigned char* mBasePtr; // raw allocated pointer (for delete)
int mFloats; // size of buffer (w/out padding)
// ctor
AlignedFloatBuffer();
// Allocate and align buffer
result init(unsigned int aFloats);
// Clear data to zero.
void clear();
// dtor
~AlignedFloatBuffer();
};
namespace SoLoud
// Lightweight class that handles small aligned buffer to support vectorized operations
class TinyAlignedFloatBuffer
{
// Class that handles aligned allocations to support vectorized operations
class AlignedFloatBuffer
{
public:
float *mData; // aligned pointer
unsigned char *mBasePtr; // raw allocated pointer (for delete)
int mFloats; // size of buffer (w/out padding)
public:
float* mData; // aligned pointer
unsigned char mActualData[sizeof(float) * 16 + 16];
// ctor
AlignedFloatBuffer();
// Allocate and align buffer
result init(unsigned int aFloats);
// Clear data to zero.
void clear();
// dtor
~AlignedFloatBuffer();
};
// Lightweight class that handles small aligned buffer to support vectorized operations
class TinyAlignedFloatBuffer
{
public:
float *mData; // aligned pointer
unsigned char mActualData[sizeof(float) * 16 + 16];
// ctor
TinyAlignedFloatBuffer();
};
// ctor
TinyAlignedFloatBuffer();
};
}
#include "soloud_filter.h"
#include "soloud_fader.h"
@ -149,408 +148,421 @@ namespace SoLoud
#include "soloud_queue.h"
#include "soloud_error.h"
namespace SoLoud
namespace SoLoud {
// Soloud core class.
class Soloud
{
public:
// Back-end data; content is up to the back-end implementation.
void* mBackendData;
// Pointer for the audio thread mutex.
void* mAudioThreadMutex;
// Flag for when we're inside the mutex, used for debugging.
bool mInsideAudioThreadMutex;
// Called by SoLoud to shut down the back-end. If NULL, not called. Should be set by back-end.
soloudCallFunction mBackendCleanupFunc;
// Soloud core class.
class Soloud
{
public:
// Back-end data; content is up to the back-end implementation.
void * mBackendData;
// Pointer for the audio thread mutex.
void * mAudioThreadMutex;
// Flag for when we're inside the mutex, used for debugging.
bool mInsideAudioThreadMutex;
// Called by SoLoud to shut down the back-end. If NULL, not called. Should be set by back-end.
soloudCallFunction mBackendCleanupFunc;
// CTor
Soloud();
// DTor
~Soloud();
// CTor
Soloud();
// DTor
~Soloud();
enum BACKENDS
{
AUTO = 0,
MUAUDIO,
SDL1,
SDL2,
PORTAUDIO,
WINMM,
XAUDIO2,
WASAPI,
ALSA,
JACK,
OSS,
OPENAL,
COREAUDIO,
OPENSLES,
VITA_HOMEBREW,
MINIAUDIO,
NOSOUND,
NULLDRIVER,
BACKEND_MAX,
};
enum BACKENDS
{
AUTO = 0,
MUAUDIO,
SDL1,
SDL2,
PORTAUDIO,
WINMM,
XAUDIO2,
WASAPI,
ALSA,
JACK,
OSS,
OPENAL,
COREAUDIO,
OPENSLES,
VITA_HOMEBREW,
MINIAUDIO,
NOSOUND,
NULLDRIVER,
BACKEND_MAX,
};
enum FLAGS
{
// Use round-off clipper
CLIP_ROUNDOFF = 1,
ENABLE_VISUALIZATION = 2,
LEFT_HANDED_3D = 4,
NO_FPU_REGISTER_CHANGE = 8
};
enum FLAGS
{
// Use round-off clipper
CLIP_ROUNDOFF = 1,
ENABLE_VISUALIZATION = 2,
LEFT_HANDED_3D = 4,
NO_FPU_REGISTER_CHANGE = 8
};
// Initialize SoLoud. Must be called before SoLoud can be used.
result init(unsigned int aFlags = Soloud::CLIP_ROUNDOFF, unsigned int aBackend = Soloud::AUTO,
unsigned int aSamplerate = Soloud::AUTO, unsigned int aBufferSize = Soloud::AUTO,
unsigned int aChannels = 2);
// Initialize SoLoud. Must be called before SoLoud can be used.
result init(unsigned int aFlags = Soloud::CLIP_ROUNDOFF, unsigned int aBackend = Soloud::AUTO, unsigned int aSamplerate = Soloud::AUTO, unsigned int aBufferSize = Soloud::AUTO, unsigned int aChannels = 2);
// Deinitialize SoLoud. Must be called before shutting down.
void deinit();
// Deinitialize SoLoud. Must be called before shutting down.
void deinit();
// Query SoLoud version number (should equal to SOLOUD_VERSION macro)
unsigned int getVersion() const;
// Query SoLoud version number (should equal to SOLOUD_VERSION macro)
unsigned int getVersion() const;
// Translate error number to an asciiz string
const char* getErrorString(result aErrorCode) const;
// Translate error number to an asciiz string
const char * getErrorString(result aErrorCode) const;
// Returns current backend ID (BACKENDS enum)
unsigned int getBackendId();
// Returns current backend string. May be NULL.
const char* getBackendString();
// Returns current backend channel count (1 mono, 2 stereo, etc)
unsigned int getBackendChannels();
// Returns current backend sample rate
unsigned int getBackendSamplerate();
// Returns current backend buffer size
unsigned int getBackendBufferSize();
// Returns current backend ID (BACKENDS enum)
unsigned int getBackendId();
// Returns current backend string. May be NULL.
const char * getBackendString();
// Returns current backend channel count (1 mono, 2 stereo, etc)
unsigned int getBackendChannels();
// Returns current backend sample rate
unsigned int getBackendSamplerate();
// Returns current backend buffer size
unsigned int getBackendBufferSize();
// Set speaker position in 3d space
result setSpeakerPosition(unsigned int aChannel, float aX, float aY, float aZ);
// Get speaker position in 3d space
result getSpeakerPosition(unsigned int aChannel, float& aX, float& aY, float& aZ);
// Set speaker position in 3d space
result setSpeakerPosition(unsigned int aChannel, float aX, float aY, float aZ);
// Get speaker position in 3d space
result getSpeakerPosition(unsigned int aChannel, float &aX, float &aY, float &aZ);
// Start playing a sound. Returns voice handle, which can be ignored or used to alter the playing sound's parameters. Negative volume means to use default.
handle play(AudioSource& aSound, float aVolume = -1.0f, float aPan = 0.0f, bool aPaused = 0, unsigned int aBus = 0);
// Start playing a sound delayed in relation to other sounds called via this function. Negative volume means to use default.
handle playClocked(time aSoundTime, AudioSource& aSound, float aVolume = -1.0f, float aPan = 0.0f,
unsigned int aBus = 0);
// Start playing a 3d audio source
handle play3d(AudioSource& aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f,
float aVelZ = 0.0f, float aVolume = 1.0f, bool aPaused = 0, unsigned int aBus = 0);
// Start playing a 3d audio source, delayed in relation to other sounds called via this function.
handle play3dClocked(time aSoundTime, AudioSource& aSound, float aPosX, float aPosY, float aPosZ,
float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f,
unsigned int aBus = 0);
// Start playing a sound without any panning. It will be played at full volume.
handle playBackground(AudioSource& aSound, float aVolume = -1.0f, bool aPaused = 0, unsigned int aBus = 0);
// Start playing a sound. Returns voice handle, which can be ignored or used to alter the playing sound's parameters. Negative volume means to use default.
handle play(AudioSource &aSound, float aVolume = -1.0f, float aPan = 0.0f, bool aPaused = 0, unsigned int aBus = 0);
// Start playing a sound delayed in relation to other sounds called via this function. Negative volume means to use default.
handle playClocked(time aSoundTime, AudioSource &aSound, float aVolume = -1.0f, float aPan = 0.0f, unsigned int aBus = 0);
// Start playing a 3d audio source
handle play3d(AudioSource &aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, bool aPaused = 0, unsigned int aBus = 0);
// Start playing a 3d audio source, delayed in relation to other sounds called via this function.
handle play3dClocked(time aSoundTime, AudioSource &aSound, float aPosX, float aPosY, float aPosZ, float aVelX = 0.0f, float aVelY = 0.0f, float aVelZ = 0.0f, float aVolume = 1.0f, unsigned int aBus = 0);
// Start playing a sound without any panning. It will be played at full volume.
handle playBackground(AudioSource &aSound, float aVolume = -1.0f, bool aPaused = 0, unsigned int aBus = 0);
// Seek the audio stream to certain point in time. Some streams can't seek backwards. Relative play speed affects time.
result seek(handle aVoiceHandle, time aSeconds);
// Stop the sound.
void stop(handle aVoiceHandle);
// Stop all voices.
void stopAll();
// Stop all voices that play this sound source
void stopAudioSource(AudioSource& aSound);
// Count voices that play this audio source
int countAudioSource(AudioSource& aSound);
// Seek the audio stream to certain point in time. Some streams can't seek backwards. Relative play speed affects time.
result seek(handle aVoiceHandle, time aSeconds);
// Stop the sound.
void stop(handle aVoiceHandle);
// Stop all voices.
void stopAll();
// Stop all voices that play this sound source
void stopAudioSource(AudioSource &aSound);
// Count voices that play this audio source
int countAudioSource(AudioSource &aSound);
// Set a live filter parameter. Use 0 for the global filters.
void setFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId, float aValue);
// Get a live filter parameter. Use 0 for the global filters.
float getFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId);
// Fade a live filter parameter. Use 0 for the global filters.
void fadeFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId, float aTo,
time aTime);
// Oscillate a live filter parameter. Use 0 for the global filters.
void oscillateFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId, float aFrom,
float aTo, time aTime);
// Set a live filter parameter. Use 0 for the global filters.
void setFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId, float aValue);
// Get a live filter parameter. Use 0 for the global filters.
float getFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId);
// Fade a live filter parameter. Use 0 for the global filters.
void fadeFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId, float aTo, time aTime);
// Oscillate a live filter parameter. Use 0 for the global filters.
void oscillateFilterParameter(handle aVoiceHandle, unsigned int aFilterId, unsigned int aAttributeId, float aFrom, float aTo, time aTime);
// Get current play time, in seconds.
time getStreamTime(handle aVoiceHandle);
// Get current sample position, in seconds.
time getStreamPosition(handle aVoiceHandle);
// Get current pause state.
bool getPause(handle aVoiceHandle);
// Get current volume.
float getVolume(handle aVoiceHandle);
// Get current overall volume (set volume * 3d volume)
float getOverallVolume(handle aVoiceHandle);
// Get current pan.
float getPan(handle aVoiceHandle);
// Get current sample rate.
float getSamplerate(handle aVoiceHandle);
// Get current voice protection state.
bool getProtectVoice(handle aVoiceHandle);
// Get the current number of busy voices.
unsigned int getActiveVoiceCount();
// Get the current number of voices in SoLoud
unsigned int getVoiceCount();
// Check if the handle is still valid, or if the sound has stopped.
bool isValidVoiceHandle(handle aVoiceHandle);
// Get current relative play speed.
float getRelativePlaySpeed(handle aVoiceHandle);
// Get current post-clip scaler value.
float getPostClipScaler() const;
// Get current global volume
float getGlobalVolume() const;
// Get current maximum active voice setting
unsigned int getMaxActiveVoiceCount() const;
// Query whether a voice is set to loop.
bool getLooping(handle aVoiceHandle);
// Get voice loop point value
time getLoopPoint(handle aVoiceHandle);
// Get current play time, in seconds.
time getStreamTime(handle aVoiceHandle);
// Get current sample position, in seconds.
time getStreamPosition(handle aVoiceHandle);
// Get current pause state.
bool getPause(handle aVoiceHandle);
// Get current volume.
float getVolume(handle aVoiceHandle);
// Get current overall volume (set volume * 3d volume)
float getOverallVolume(handle aVoiceHandle);
// Get current pan.
float getPan(handle aVoiceHandle);
// Get current sample rate.
float getSamplerate(handle aVoiceHandle);
// Get current voice protection state.
bool getProtectVoice(handle aVoiceHandle);
// Get the current number of busy voices.
unsigned int getActiveVoiceCount();
// Get the current number of voices in SoLoud
unsigned int getVoiceCount();
// Check if the handle is still valid, or if the sound has stopped.
bool isValidVoiceHandle(handle aVoiceHandle);
// Get current relative play speed.
float getRelativePlaySpeed(handle aVoiceHandle);
// Get current post-clip scaler value.
float getPostClipScaler() const;
// Get current global volume
float getGlobalVolume() const;
// Get current maximum active voice setting
unsigned int getMaxActiveVoiceCount() const;
// Query whether a voice is set to loop.
bool getLooping(handle aVoiceHandle);
// Get voice loop point value
time getLoopPoint(handle aVoiceHandle);
// Set voice loop point value
void setLoopPoint(handle aVoiceHandle, time aLoopPoint);
// Set voice's loop state
void setLooping(handle aVoiceHandle, bool aLooping);
// Set current maximum active voice setting
result setMaxActiveVoiceCount(unsigned int aVoiceCount);
// Set behavior for inaudible sounds
void setInaudibleBehavior(handle aVoiceHandle, bool aMustTick, bool aKill);
// Set the global volume
void setGlobalVolume(float aVolume);
// Set the post clip scaler value
void setPostClipScaler(float aScaler);
// Set the pause state
void setPause(handle aVoiceHandle, bool aPause);
// Pause all voices
void setPauseAll(bool aPause);
// Set the relative play speed
result setRelativePlaySpeed(handle aVoiceHandle, float aSpeed);
// Set the voice protection state
void setProtectVoice(handle aVoiceHandle, bool aProtect);
// Set the sample rate
void setSamplerate(handle aVoiceHandle, float aSamplerate);
// Set panning value; -1 is left, 0 is center, 1 is right
void setPan(handle aVoiceHandle, float aPan);
// Set absolute left/right volumes
void setPanAbsolute(handle aVoiceHandle, float aLVolume, float aRVolume, float aLBVolume = 0, float aRBVolume = 0,
float aCVolume = 0, float aSVolume = 0);
// Set overall volume
void setVolume(handle aVoiceHandle, float aVolume);
// Set delay, in samples, before starting to play samples. Calling this on a live sound will cause glitches.
void setDelaySamples(handle aVoiceHandle, unsigned int aSamples);
// Set voice loop point value
void setLoopPoint(handle aVoiceHandle, time aLoopPoint);
// Set voice's loop state
void setLooping(handle aVoiceHandle, bool aLooping);
// Set current maximum active voice setting
result setMaxActiveVoiceCount(unsigned int aVoiceCount);
// Set behavior for inaudible sounds
void setInaudibleBehavior(handle aVoiceHandle, bool aMustTick, bool aKill);
// Set the global volume
void setGlobalVolume(float aVolume);
// Set the post clip scaler value
void setPostClipScaler(float aScaler);
// Set the pause state
void setPause(handle aVoiceHandle, bool aPause);
// Pause all voices
void setPauseAll(bool aPause);
// Set the relative play speed
result setRelativePlaySpeed(handle aVoiceHandle, float aSpeed);
// Set the voice protection state
void setProtectVoice(handle aVoiceHandle, bool aProtect);
// Set the sample rate
void setSamplerate(handle aVoiceHandle, float aSamplerate);
// Set panning value; -1 is left, 0 is center, 1 is right
void setPan(handle aVoiceHandle, float aPan);
// Set absolute left/right volumes
void setPanAbsolute(handle aVoiceHandle, float aLVolume, float aRVolume, float aLBVolume = 0, float aRBVolume = 0, float aCVolume = 0, float aSVolume = 0);
// Set overall volume
void setVolume(handle aVoiceHandle, float aVolume);
// Set delay, in samples, before starting to play samples. Calling this on a live sound will cause glitches.
void setDelaySamples(handle aVoiceHandle, unsigned int aSamples);
// Set up volume fader
void fadeVolume(handle aVoiceHandle, float aTo, time aTime);
// Set up panning fader
void fadePan(handle aVoiceHandle, float aTo, time aTime);
// Set up relative play speed fader
void fadeRelativePlaySpeed(handle aVoiceHandle, float aTo, time aTime);
// Set up global volume fader
void fadeGlobalVolume(float aTo, time aTime);
// Schedule a stream to pause
void schedulePause(handle aVoiceHandle, time aTime);
// Schedule a stream to stop
void scheduleStop(handle aVoiceHandle, time aTime);
// Set up volume fader
void fadeVolume(handle aVoiceHandle, float aTo, time aTime);
// Set up panning fader
void fadePan(handle aVoiceHandle, float aTo, time aTime);
// Set up relative play speed fader
void fadeRelativePlaySpeed(handle aVoiceHandle, float aTo, time aTime);
// Set up global volume fader
void fadeGlobalVolume(float aTo, time aTime);
// Schedule a stream to pause
void schedulePause(handle aVoiceHandle, time aTime);
// Schedule a stream to stop
void scheduleStop(handle aVoiceHandle, time aTime);
// Set up volume oscillator
void oscillateVolume(handle aVoiceHandle, float aFrom, float aTo, time aTime);
// Set up panning oscillator
void oscillatePan(handle aVoiceHandle, float aFrom, float aTo, time aTime);
// Set up relative play speed oscillator
void oscillateRelativePlaySpeed(handle aVoiceHandle, float aFrom, float aTo, time aTime);
// Set up global volume oscillator
void oscillateGlobalVolume(float aFrom, float aTo, time aTime);
// Set up volume oscillator
void oscillateVolume(handle aVoiceHandle, float aFrom, float aTo, time aTime);
// Set up panning oscillator
void oscillatePan(handle aVoiceHandle, float aFrom, float aTo, time aTime);
// Set up relative play speed oscillator
void oscillateRelativePlaySpeed(handle aVoiceHandle, float aFrom, float aTo, time aTime);
// Set up global volume oscillator
void oscillateGlobalVolume(float aFrom, float aTo, time aTime);
// Set global filters. Set to NULL to clear the filter.
void setGlobalFilter(unsigned int aFilterId, Filter* aFilter);
// Set global filters. Set to NULL to clear the filter.
void setGlobalFilter(unsigned int aFilterId, Filter *aFilter);
// Enable or disable visualization data gathering
void setVisualizationEnable(bool aEnable);
// Enable or disable visualization data gathering
void setVisualizationEnable(bool aEnable);
// Calculate and get 256 floats of FFT data for visualization. Visualization has to be enabled before use.
float* calcFFT();
// Calculate and get 256 floats of FFT data for visualization. Visualization has to be enabled before use.
float *calcFFT();
// Get 256 floats of wave data for visualization. Visualization has to be enabled before use.
float* getWave();
// Get 256 floats of wave data for visualization. Visualization has to be enabled before use.
float *getWave();
// Get approximate output volume for a channel for visualization. Visualization has to be enabled before use.
float getApproximateVolume(unsigned int aChannel);
// Get approximate output volume for a channel for visualization. Visualization has to be enabled before use.
float getApproximateVolume(unsigned int aChannel);
// Get current loop count. Returns 0 if handle is not valid. (All audio sources may not update loop count)
unsigned int getLoopCount(handle aVoiceHandle);
// Get current loop count. Returns 0 if handle is not valid. (All audio sources may not update loop count)
unsigned int getLoopCount(handle aVoiceHandle);
// Get audiosource-specific information from a voice.
float getInfo(handle aVoiceHandle, unsigned int aInfoKey);
// Get audiosource-specific information from a voice.
float getInfo(handle aVoiceHandle, unsigned int aInfoKey);
// Create a voice group. Returns 0 if unable (out of voice groups / out of memory)
handle createVoiceGroup();
// Destroy a voice group.
result destroyVoiceGroup(handle aVoiceGroupHandle);
// Add a voice handle to a voice group
result addVoiceToGroup(handle aVoiceGroupHandle, handle aVoiceHandle);
// Is this handle a valid voice group?
bool isVoiceGroup(handle aVoiceGroupHandle);
// Is this voice group empty?
bool isVoiceGroupEmpty(handle aVoiceGroupHandle);
// Create a voice group. Returns 0 if unable (out of voice groups / out of memory)
handle createVoiceGroup();
// Destroy a voice group.
result destroyVoiceGroup(handle aVoiceGroupHandle);
// Add a voice handle to a voice group
result addVoiceToGroup(handle aVoiceGroupHandle, handle aVoiceHandle);
// Is this handle a valid voice group?
bool isVoiceGroup(handle aVoiceGroupHandle);
// Is this voice group empty?
bool isVoiceGroupEmpty(handle aVoiceGroupHandle);
// Perform 3d audio parameter update
void update3dAudio();
// Perform 3d audio parameter update
void update3dAudio();
// Set the speed of sound constant for doppler
result set3dSoundSpeed(float aSpeed);
// Get the current speed of sound constant for doppler
float get3dSoundSpeed();
// Set 3d listener parameters
void set3dListenerParameters(float aPosX, float aPosY, float aPosZ, float aAtX, float aAtY, float aAtZ, float aUpX,
float aUpY, float aUpZ, float aVelocityX = 0.0f, float aVelocityY = 0.0f,
float aVelocityZ = 0.0f);
// Set 3d listener position
void set3dListenerPosition(float aPosX, float aPosY, float aPosZ);
// Set 3d listener "at" vector
void set3dListenerAt(float aAtX, float aAtY, float aAtZ);
// set 3d listener "up" vector
void set3dListenerUp(float aUpX, float aUpY, float aUpZ);
// Set 3d listener velocity
void set3dListenerVelocity(float aVelocityX, float aVelocityY, float aVelocityZ);
// Set the speed of sound constant for doppler
result set3dSoundSpeed(float aSpeed);
// Get the current speed of sound constant for doppler
float get3dSoundSpeed();
// Set 3d listener parameters
void set3dListenerParameters(float aPosX, float aPosY, float aPosZ, float aAtX, float aAtY, float aAtZ, float aUpX, float aUpY, float aUpZ, float aVelocityX = 0.0f, float aVelocityY = 0.0f, float aVelocityZ = 0.0f);
// Set 3d listener position
void set3dListenerPosition(float aPosX, float aPosY, float aPosZ);
// Set 3d listener "at" vector
void set3dListenerAt(float aAtX, float aAtY, float aAtZ);
// set 3d listener "up" vector
void set3dListenerUp(float aUpX, float aUpY, float aUpZ);
// Set 3d listener velocity
void set3dListenerVelocity(float aVelocityX, float aVelocityY, float aVelocityZ);
// Set 3d audio source parameters
void set3dSourceParameters(handle aVoiceHandle, float aPosX, float aPosY, float aPosZ, float aVelocityX = 0.0f,
float aVelocityY = 0.0f, float aVelocityZ = 0.0f);
// Set 3d audio source position
void set3dSourcePosition(handle aVoiceHandle, float aPosX, float aPosY, float aPosZ);
// Set 3d audio source velocity
void set3dSourceVelocity(handle aVoiceHandle, float aVelocityX, float aVelocityY, float aVelocityZ);
// Set 3d audio source min/max distance (distance < min means max volume)
void set3dSourceMinMaxDistance(handle aVoiceHandle, float aMinDistance, float aMaxDistance);
// Set 3d audio source attenuation parameters
void set3dSourceAttenuation(handle aVoiceHandle, unsigned int aAttenuationModel, float aAttenuationRolloffFactor);
// Set 3d audio source doppler factor to reduce or enhance doppler effect. Default = 1.0
void set3dSourceDopplerFactor(handle aVoiceHandle, float aDopplerFactor);
// Set 3d audio source parameters
void set3dSourceParameters(handle aVoiceHandle, float aPosX, float aPosY, float aPosZ, float aVelocityX = 0.0f, float aVelocityY = 0.0f, float aVelocityZ = 0.0f);
// Set 3d audio source position
void set3dSourcePosition(handle aVoiceHandle, float aPosX, float aPosY, float aPosZ);
// Set 3d audio source velocity
void set3dSourceVelocity(handle aVoiceHandle, float aVelocityX, float aVelocityY, float aVelocityZ);
// Set 3d audio source min/max distance (distance < min means max volume)
void set3dSourceMinMaxDistance(handle aVoiceHandle, float aMinDistance, float aMaxDistance);
// Set 3d audio source attenuation parameters
void set3dSourceAttenuation(handle aVoiceHandle, unsigned int aAttenuationModel, float aAttenuationRolloffFactor);
// Set 3d audio source doppler factor to reduce or enhance doppler effect. Default = 1.0
void set3dSourceDopplerFactor(handle aVoiceHandle, float aDopplerFactor);
// Rest of the stuff is used internally.
// Rest of the stuff is used internally.
// Returns mixed float samples in buffer. Called by the back-end, or user with null driver.
void mix(float* aBuffer, unsigned int aSamples);
// Returns mixed 16-bit signed integer samples in buffer. Called by the back-end, or user with null driver.
void mixSigned16(short* aBuffer, unsigned int aSamples);
public:
// Mix N samples * M channels. Called by other mix_ functions.
void mix_internal(unsigned int aSamples);
// Returns mixed float samples in buffer. Called by the back-end, or user with null driver.
void mix(float *aBuffer, unsigned int aSamples);
// Returns mixed 16-bit signed integer samples in buffer. Called by the back-end, or user with null driver.
void mixSigned16(short *aBuffer, unsigned int aSamples);
public:
// Mix N samples * M channels. Called by other mix_ functions.
void mix_internal(unsigned int aSamples);
// Handle rest of initialization (called from backend)
void postinit_internal(unsigned int aSamplerate, unsigned int aBufferSize, unsigned int aFlags,
unsigned int aChannels);
// Handle rest of initialization (called from backend)
void postinit_internal(unsigned int aSamplerate, unsigned int aBufferSize, unsigned int aFlags, unsigned int aChannels);
// Update list of active voices
void calcActiveVoices_internal();
// Map resample buffers to active voices
void mapResampleBuffers_internal();
// Perform mixing for a specific bus
void mixBus_internal(float* aBuffer, unsigned int aSamplesToRead, unsigned int aBufferSize, float* aScratch,
unsigned int aBus, float aSamplerate, unsigned int aChannels);
// Find a free voice, stopping the oldest if no free voice is found.
int findFreeVoice_internal();
// Converts handle to voice, if the handle is valid. Returns -1 if not.
int getVoiceFromHandle_internal(handle aVoiceHandle) const;
// Converts voice + playindex into handle
handle getHandleFromVoice_internal(unsigned int aVoice) const;
// Stop voice (not handle).
void stopVoice_internal(unsigned int aVoice);
// Set voice (not handle) pan.
void setVoicePan_internal(unsigned int aVoice, float aPan);
// Set voice (not handle) relative play speed.
result setVoiceRelativePlaySpeed_internal(unsigned int aVoice, float aSpeed);
// Set voice (not handle) volume.
void setVoiceVolume_internal(unsigned int aVoice, float aVolume);
// Set voice (not handle) pause state.
void setVoicePause_internal(unsigned int aVoice, int aPause);
// Update overall volume from set and 3d volumes
void updateVoiceVolume_internal(unsigned int aVoice);
// Update overall relative play speed from set and 3d speeds
void updateVoiceRelativePlaySpeed_internal(unsigned int aVoice);
// Perform 3d audio calculation for array of voices
void update3dVoices_internal(unsigned int* aVoiceList, unsigned int aVoiceCount);
// Clip the samples in the buffer
void clip_internal(AlignedFloatBuffer& aBuffer, AlignedFloatBuffer& aDestBuffer, unsigned int aSamples,
float aVolume0, float aVolume1);
// Remove all non-active voices from group
void trimVoiceGroup_internal(handle aVoiceGroupHandle);
// Get pointer to the zero-terminated array of voice handles in a voice group
handle* voiceGroupHandleToArray_internal(handle aVoiceGroupHandle) const;
// Update list of active voices
void calcActiveVoices_internal();
// Map resample buffers to active voices
void mapResampleBuffers_internal();
// Perform mixing for a specific bus
void mixBus_internal(float *aBuffer, unsigned int aSamplesToRead, unsigned int aBufferSize, float *aScratch, unsigned int aBus, float aSamplerate, unsigned int aChannels);
// Find a free voice, stopping the oldest if no free voice is found.
int findFreeVoice_internal();
// Converts handle to voice, if the handle is valid. Returns -1 if not.
int getVoiceFromHandle_internal(handle aVoiceHandle) const;
// Converts voice + playindex into handle
handle getHandleFromVoice_internal(unsigned int aVoice) const;
// Stop voice (not handle).
void stopVoice_internal(unsigned int aVoice);
// Set voice (not handle) pan.
void setVoicePan_internal(unsigned int aVoice, float aPan);
// Set voice (not handle) relative play speed.
result setVoiceRelativePlaySpeed_internal(unsigned int aVoice, float aSpeed);
// Set voice (not handle) volume.
void setVoiceVolume_internal(unsigned int aVoice, float aVolume);
// Set voice (not handle) pause state.
void setVoicePause_internal(unsigned int aVoice, int aPause);
// Update overall volume from set and 3d volumes
void updateVoiceVolume_internal(unsigned int aVoice);
// Update overall relative play speed from set and 3d speeds
void updateVoiceRelativePlaySpeed_internal(unsigned int aVoice);
// Perform 3d audio calculation for array of voices
void update3dVoices_internal(unsigned int *aVoiceList, unsigned int aVoiceCount);
// Clip the samples in the buffer
void clip_internal(AlignedFloatBuffer &aBuffer, AlignedFloatBuffer &aDestBuffer, unsigned int aSamples, float aVolume0, float aVolume1);
// Remove all non-active voices from group
void trimVoiceGroup_internal(handle aVoiceGroupHandle);
// Get pointer to the zero-terminated array of voice handles in a voice group
handle * voiceGroupHandleToArray_internal(handle aVoiceGroupHandle) const;
// Lock audio thread mutex.
void lockAudioMutex_internal();
// Unlock audio thread mutex.
void unlockAudioMutex_internal();
// Lock audio thread mutex.
void lockAudioMutex_internal();
// Unlock audio thread mutex.
void unlockAudioMutex_internal();
// Max. number of active voices. Busses and tickable inaudibles also count against this.
unsigned int mMaxActiveVoices;
// Highest voice in use so far
unsigned int mHighestVoice;
// Scratch buffer, used for resampling.
AlignedFloatBuffer mScratch;
// Current size of the scratch, in samples.
unsigned int mScratchSize;
// Amount of scratch needed.
unsigned int mScratchNeeded;
// Output scratch buffer, used in mix_().
AlignedFloatBuffer mOutputScratch;
// Resampler buffers, two per active voice.
AlignedFloatBuffer* mResampleData;
// Owners of the resample data
AudioSourceInstance** mResampleDataOwner;
// Audio voices.
AudioSourceInstance* mVoice[VOICE_COUNT];
// Output sample rate (not float)
unsigned int mSamplerate;
// Output channel count
unsigned int mChannels;
// Current backend ID
unsigned int mBackendID;
// Current backend string
const char* mBackendString;
// Maximum size of output buffer; used to calculate needed scratch.
unsigned int mBufferSize;
// Flags; see Soloud::FLAGS
unsigned int mFlags;
// Global volume. Applied before clipping.
float mGlobalVolume;
// Post-clip scaler. Applied after clipping.
float mPostClipScaler;
// Current play index. Used to create audio handles.
unsigned int mPlayIndex;
// Current sound source index. Used to create sound source IDs.
unsigned int mAudioSourceID;
// Fader for the global volume.
Fader mGlobalVolumeFader;
// Global stream time, for the global volume fader.
time mStreamTime;
// Last time seen by the playClocked call
time mLastClockedTime;
// Global filter
Filter* mFilter[FILTERS_PER_STREAM];
// Global filter instance
FilterInstance* mFilterInstance[FILTERS_PER_STREAM];
// Max. number of active voices. Busses and tickable inaudibles also count against this.
unsigned int mMaxActiveVoices;
// Highest voice in use so far
unsigned int mHighestVoice;
// Scratch buffer, used for resampling.
AlignedFloatBuffer mScratch;
// Current size of the scratch, in samples.
unsigned int mScratchSize;
// Amount of scratch needed.
unsigned int mScratchNeeded;
// Output scratch buffer, used in mix_().
AlignedFloatBuffer mOutputScratch;
// Resampler buffers, two per active voice.
AlignedFloatBuffer *mResampleData;
// Owners of the resample data
AudioSourceInstance **mResampleDataOwner;
// Audio voices.
AudioSourceInstance *mVoice[VOICE_COUNT];
// Output sample rate (not float)
unsigned int mSamplerate;
// Output channel count
unsigned int mChannels;
// Current backend ID
unsigned int mBackendID;
// Current backend string
const char * mBackendString;
// Maximum size of output buffer; used to calculate needed scratch.
unsigned int mBufferSize;
// Flags; see Soloud::FLAGS
unsigned int mFlags;
// Global volume. Applied before clipping.
float mGlobalVolume;
// Post-clip scaler. Applied after clipping.
float mPostClipScaler;
// Current play index. Used to create audio handles.
unsigned int mPlayIndex;
// Current sound source index. Used to create sound source IDs.
unsigned int mAudioSourceID;
// Fader for the global volume.
Fader mGlobalVolumeFader;
// Global stream time, for the global volume fader.
time mStreamTime;
// Last time seen by the playClocked call
time mLastClockedTime;
// Global filter
Filter *mFilter[FILTERS_PER_STREAM];
// Global filter instance
FilterInstance *mFilterInstance[FILTERS_PER_STREAM];
// Approximate volume for channels.
float mVisualizationChannelVolume[MAX_CHANNELS];
// Mono-mixed wave data for visualization and for visualization FFT input
float mVisualizationWaveData[256];
// FFT output data
float mFFTData[256];
// Snapshot of wave data for visualization
float mWaveData[256];
// Approximate volume for channels.
float mVisualizationChannelVolume[MAX_CHANNELS];
// Mono-mixed wave data for visualization and for visualization FFT input
float mVisualizationWaveData[256];
// FFT output data
float mFFTData[256];
// Snapshot of wave data for visualization
float mWaveData[256];
// 3d listener position
float m3dPosition[3];
// 3d listener look-at
float m3dAt[3];
// 3d listener up
float m3dUp[3];
// 3d listener velocity
float m3dVelocity[3];
// 3d speed of sound (for doppler)
float m3dSoundSpeed;
// 3d listener position
float m3dPosition[3];
// 3d listener look-at
float m3dAt[3];
// 3d listener up
float m3dUp[3];
// 3d listener velocity
float m3dVelocity[3];
// 3d speed of sound (for doppler)
float m3dSoundSpeed;
// 3d position of speakers
float m3dSpeakerPosition[3 * MAX_CHANNELS];
// 3d position of speakers
float m3dSpeakerPosition[3 * MAX_CHANNELS];
// Data related to 3d processing, separate from AudioSource so we can do 3d calculations without audio mutex.
AudioSourceInstance3dData m3dData[VOICE_COUNT];
// Data related to 3d processing, separate from AudioSource so we can do 3d calculations without audio mutex.
AudioSourceInstance3dData m3dData[VOICE_COUNT];
// For each voice group, first int is number of ints alocated.
unsigned int** mVoiceGroup;
unsigned int mVoiceGroupCount;
// For each voice group, first int is number of ints alocated.
unsigned int **mVoiceGroup;
unsigned int mVoiceGroupCount;
// List of currently active voices
unsigned int mActiveVoice[VOICE_COUNT];
// Number of currently active voices
unsigned int mActiveVoiceCount;
// Active voices list needs to be recalculated
bool mActiveVoiceDirty;
};
// List of currently active voices
unsigned int mActiveVoice[VOICE_COUNT];
// Number of currently active voices
unsigned int mActiveVoiceCount;
// Active voices list needs to be recalculated
bool mActiveVoiceDirty;
};
}
#endif

View file

@ -82,12 +82,8 @@ void AudioEngineDevTools::playNotation()
return;
}
<< << << < HEAD
auto stream = notation->playback()->midiStream();
==
== ===auto stream = notation->midiData()->midiStream();
>> >> >> > a9e5ceef7 ... added notation midi data
player()->setMidiStream(stream);
auto stream = notation->playback()->midiStream();
player()->setMidiStream(stream);
player()->play();
}
@ -98,19 +94,12 @@ void AudioEngineDevTools::stopNotation()
void AudioEngineDevTools::makeArpeggio()
{
<< << << < HEAD
if (m_midiStream) {
return;
}
m_midiStream = std::make_shared<midi::MidiStream>();
==
== ===if (m_midiStream.isValid()) {
if (m_midiStream) {
return;
}
>> >> >> > a9e5ceef7 ... added notation midi data
m_midiStream = std::make_shared<midi::MidiStream>();
auto makeEvents = [](Channel& ch, uint32_t tick, int pitch) {
/* notes of the arpeggio */
static std::vector<int> notes = { 60, 64, 67, 72, 76, 79, 84, 79, 76, 72, 67, 64 };

View file

@ -246,7 +246,8 @@ ValCh<PlayStatus> AudioPlayer::status() const
void AudioPlayer::onPlayCallbackCalled()
{
//! NOTE For tests in development
<< << << < HEAD
//! NOTE For tests in development
// struct Time {
// QElapsedTimer time;
// int last = 0;
@ -268,4 +269,27 @@ void AudioPlayer::onPlayCallbackCalled()
// LOGI() << "[onPlayCallbackCalled] pos: " << p << ", delta pos: " << deltaPos << ", timer: " << delta;
// }
==
== ===struct Time {
QElapsedTimer time;
int last = 0;
Time() { time.start(); }
};
static Time time;
static float lastPos = 0;
if (m_status.val == PlayStatus::PLAYING) {
float p = playbackPosition();
float deltaPos = p - lastPos;
lastPos = p;
int cur = time.time.elapsed();
int delta = cur - time.last;
time.last = cur;
LOGI() << "[onPlayCallbackCalled] pos: " << p << ", delta pos: " << deltaPos << ", timer: " << delta;
}
>> >> >> > 53111275d ... added playback cursor
}

View file

@ -34,11 +34,7 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/notationtypes.h
${CMAKE_CURRENT_LIST_DIR}/inotationconfiguration.h
${CMAKE_CURRENT_LIST_DIR}/notationerrors.h
<<<<<<< HEAD
${CMAKE_CURRENT_LIST_DIR}/inotationplayback.h
=======
${CMAKE_CURRENT_LIST_DIR}/inotationmididata.h
>>>>>>> a9e5ceef7... added notation midi data
${CMAKE_CURRENT_LIST_DIR}/internal/notationactions.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/notationactions.h
${CMAKE_CURRENT_LIST_DIR}/internal/notation.cpp

View file

@ -1,38 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef MU_DOMAIN_INOTATIONMIDIDATA_H
#define MU_DOMAIN_INOTATIONMIDIDATA_H
#include "audio/midi/miditypes.h"
namespace mu {
namespace domain {
namespace notation {
class INotationMidiData
{
public:
virtual ~INotationMidiData() = default;
virtual audio::midi::MidiStream midiStream() const = 0;
};
}
}
}
#endif // MU_DOMAIN_INOTATIONMIDIDATA_H

View file

@ -45,11 +45,6 @@
#include "libmscore/synthesizerstate.h"
#include "../notationerrors.h"
<< << << < HEAD
== == ===
#include "notationinteraction.h"
#include "notationmididata.h"
>> >> >> > a9e5ceef7 ... added notation midi data
//#ifdef BUILD_UI_MU4
////! HACK Temporary hack to link libmscore
@ -64,7 +59,7 @@
////! ---------
//#endif
using namespace mu::domain::notation;
using namespace mu::domain::notation;
using namespace Ms;
Notation::Notation()

View file

@ -1,222 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "notationmididata.h"
#include <cmath>
#include "log.h"
#include "libmscore/score.h"
#include "libmscore/tempo.h"
#include "libmscore/part.h"
#include "libmscore/instrument.h"
#include "libmscore/repeatlist.h"
#include "audio/midi/event.h" //! TODO Remove me
using namespace mu::domain::notation;
using namespace mu::audio::midi;
static EventType convertType(int type)
{
switch (type) {
case Ms::ME_NOTEON: return ME_NOTEON;
case Ms::ME_NOTEOFF: return ME_NOTEOFF;
case Ms::ME_CONTROLLER: return ME_CONTROLLER;
case Ms::ME_PITCHBEND: return ME_PITCHBEND;
case Ms::ME_META: return ME_META;
case Ms::ME_TICK1: return ME_INVALID;
case Ms::ME_TICK2: return ME_INVALID;
default: {
LOGE() << "unknown midi type: " << type;
}
}
return ME_INVALID;
}
NotationMidiData::NotationMidiData(IGetScore* getScore)
: m_getScore(getScore)
{
}
MidiStream NotationMidiData::midiStream() const
{
Ms::Score* score = m_getScore->score();
if (!score) {
return MidiStream();
}
makeInitData(m_stream.initData, score);
m_stream.request.onReceive(this, [this](uint32_t tick) {
UNUSED(tick);
m_stream.stream.close();
});
return m_stream;
}
void NotationMidiData::makeInitData(MidiData& data, Ms::Score* score) const
{
MetaInfo meta;
makeMetaInfo(meta, score);
data.division = Ms::MScore::division;
data.tracks.resize(meta.tracksCount);
Ms::EventMap eventMap;
makeEventMap(eventMap, score);
fillTracks(data.tracks, eventMap, meta);
fillTempoMap(data.tempomap, score);
//fillMetronome(stream->initData.metronome, score, midiSpec);
}
void NotationMidiData::makeEventMap(Ms::EventMap& eventMap, Ms::Score* score) const
{
// int unrenderedUtick = renderEventsStatus.occupiedRangeEnd(utick);
// while (unrenderedUtick - utick < minUtickBufferSize) {
// const MidiRenderer::Chunk chunk = midi.getChunkAt(unrenderedUtick);
// if (!chunk) {
// break;
// }
// renderChunk(chunk, &events);
// unrenderedUtick = renderEventsStatus.occupiedRangeEnd(utick);
// }
score->masterScore()->setExpandRepeats(true);
score->renderMidi(&eventMap, Ms::SynthesizerState());
}
void NotationMidiData::makeMetaInfo(MetaInfo& meta, const Ms::Score* score) const
{
auto parts = score->parts();
meta.tracksCount = parts.size();
auto bankForInstrument = [](const Ms::Instrument* instr) {
//! NOTE Temporary solution
if (instr->useDrumset()) {
return 128;
}
return 0;
};
for (int pi = 0; pi < parts.size(); ++pi) {
const Ms::Part* part = parts.at(pi);
const Ms::InstrumentList* instList = part->instruments();
for (auto it = instList->cbegin(); it != instList->cend(); ++it) {
const Ms::Instrument* instrument = it->second;
uint16_t bank = bankForInstrument(instrument);
for (const Ms::Channel* ch : instrument->channel()) {
ChanInfo chi;
chi.trackIdx = pi;
chi.bank = bank;
chi.program = ch->program();
meta.channels.insert({ ch->channel(), chi });
}
}
}
}
void NotationMidiData::fillTracks(std::vector<audio::midi::Track>& tracks, const Ms::EventMap& eventMap,
const MetaInfo& meta) const
{
uint16_t ch_num = 1; //! NOTE channel 0 reserved for metronome
auto findOrAddChannel = [&ch_num](audio::midi::Track& t, const ChanInfo& chi) -> audio::midi::Channel& {
for (auto& ch : t.channels) {
if (ch.program == chi.program && ch.bank == chi.bank) {
return ch;
}
}
audio::midi::Channel ch;
ch.num = ch_num;
ch.program = chi.program;
ch.bank = chi.bank;
++ch_num;
t.channels.push_back(std::move(ch));
return t.channels.back();
};
for (const auto& evp : eventMap) {
int tick = evp.first;
const Ms::NPlayEvent ev = evp.second;
if (ev.type() == Ms::ME_CONTROLLER && ev.controller() == 2) {
//! TODO Understand why these events
continue;
}
auto foundIt = meta.channels.find(ev.channel());
if (foundIt == meta.channels.end()) {
Q_ASSERT(foundIt != meta.channels.end());
continue;
}
const ChanInfo& chi = foundIt->second;
audio::midi::Track& track = tracks.at(chi.trackIdx);
audio::midi::Channel& ch = findOrAddChannel(track, chi);
audio::midi::EventType etype = convertType(ev.type());
if (audio::midi::ME_INVALID == etype) {
continue;
} else if (audio::midi::ME_META == etype) {
continue;
} else {
audio::midi::Event e
{ static_cast<uint32_t>(tick),
etype,
ev.dataA(), ev.dataB()
};
ch.events.push_back(std::move(e));
}
}
}
void NotationMidiData::fillTempoMap(std::map<uint32_t, uint32_t>& tempos, const Ms::Score* score) const
{
Ms::TempoMap* tempomap = score->tempomap();
qreal relTempo = tempomap->relTempo();
for (const Ms::RepeatSegment* rs : score->repeatList()) {
int startTick = rs->tick, endTick = startTick + rs->len();
int tickOffset = rs->utick - rs->tick;
auto se = tempomap->lower_bound(startTick);
auto ee = tempomap->lower_bound(endTick);
for (auto it = se; it != ee; ++it) {
//
// compute midi tempo: microseconds / quarter note
//
uint32_t tempo = (uint32_t)lrint((1.0 / (it->second.tempo * relTempo)) * 1000000.0);
tempos.insert({ it->first + tickOffset, tempo });
}
}
}

View file

@ -1,66 +0,0 @@
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2020 MuseScore BVBA and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef MU_DOMAIN_NOTATIONMIDIDATA_H
#define MU_DOMAIN_NOTATIONMIDIDATA_H
#include "../inotationmididata.h"
#include "igetscore.h"
#include "async/asyncable.h"
namespace Ms {
class EventMap;
}
namespace mu {
namespace domain {
namespace notation {
class NotationMidiData : public INotationMidiData, public async::Asyncable
{
public:
NotationMidiData(IGetScore* getScore);
audio::midi::MidiStream midiStream() const override;
private:
struct ChanInfo {
size_t trackIdx{ 0 };
uint16_t bank{ 0 };
uint16_t program{ 0 };
};
struct MetaInfo {
size_t tracksCount{ 0 };
std::map<uint16_t, ChanInfo> channels;
};
void makeInitData(audio::midi::MidiData& data, Ms::Score* score) const;
void makeEventMap(Ms::EventMap& eventMap, Ms::Score* score) const;
void makeMetaInfo(MetaInfo& meta, const Ms::Score* score) const;
void fillTracks(std::vector<audio::midi::Track>& tracks, const Ms::EventMap& eventMap, const MetaInfo& meta) const;
void fillTempoMap(std::map<uint32_t /*tick*/, uint32_t /*tempo*/>& tempos, const Ms::Score* score) const;
IGetScore* m_getScore = nullptr;
mutable audio::midi::MidiStream m_stream;
};
}
}
}
#endif // MU_DOMAIN_NOTATIONMIDIDATA_H

View file

@ -30,6 +30,7 @@ namespace notation {
class PlaybackCursor
{
public:
PlaybackCursor() = default;
void paint(QPainter* painter);