mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-16 01:35:07 +00:00
Merge remote-tracking branch 'upstream/master' into macro
# Conflicts: # src/engine/platform/c64.cpp # src/gui/insEdit.cpp
This commit is contained in:
commit
ae4f005d67
41 changed files with 635 additions and 350 deletions
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
|
@ -89,6 +89,19 @@ jobs:
|
||||||
echo "::set-output name=id::${package_name}"
|
echo "::set-output name=id::${package_name}"
|
||||||
echo "::set-output name=filename::${package_name}${package_ext}"
|
echo "::set-output name=filename::${package_name}${package_ext}"
|
||||||
|
|
||||||
|
- name: Set build cores amount
|
||||||
|
id: build-cores
|
||||||
|
run: |
|
||||||
|
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
|
||||||
|
set amount=2
|
||||||
|
if [ '${{ runner.os }}' == 'macOS' ]; then
|
||||||
|
amount=3
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Amount of cores we can build with: ${amount}"
|
||||||
|
|
||||||
|
echo "::set-output name=amount::${amount}"
|
||||||
|
|
||||||
- name: Setup Toolchain [Windows MSVC]
|
- name: Setup Toolchain [Windows MSVC]
|
||||||
if: ${{ matrix.config.compiler == 'msvc' }}
|
if: ${{ matrix.config.compiler == 'msvc' }}
|
||||||
uses: seanmiddleditch/gha-setup-vsdevenv@v3
|
uses: seanmiddleditch/gha-setup-vsdevenv@v3
|
||||||
|
@ -125,9 +138,6 @@ jobs:
|
||||||
export CMAKE_EXTRA_ARGS=()
|
export CMAKE_EXTRA_ARGS=()
|
||||||
if [ '${{ matrix.config.compiler }}' == 'msvc' ]; then
|
if [ '${{ matrix.config.compiler }}' == 'msvc' ]; then
|
||||||
CMAKE_EXTRA_ARGS+=('-DCMAKE_GENERATOR_PLATFORM=${{ steps.windows-identify.outputs.msvc-target }}')
|
CMAKE_EXTRA_ARGS+=('-DCMAKE_GENERATOR_PLATFORM=${{ steps.windows-identify.outputs.msvc-target }}')
|
||||||
|
|
||||||
# FIXME We don't want all the MSVC warnings to cause errors yet
|
|
||||||
export USE_WAE=OFF
|
|
||||||
elif [ '${{ matrix.config.compiler }}' == 'mingw' ]; then
|
elif [ '${{ matrix.config.compiler }}' == 'mingw' ]; then
|
||||||
CMAKE_EXTRA_ARGS+=('-DCMAKE_TOOLCHAIN_FILE=scripts/Cross-MinGW-${{ steps.windows-identify.outputs.mingw-target }}.cmake')
|
CMAKE_EXTRA_ARGS+=('-DCMAKE_TOOLCHAIN_FILE=scripts/Cross-MinGW-${{ steps.windows-identify.outputs.mingw-target }}.cmake')
|
||||||
else
|
else
|
||||||
|
@ -159,7 +169,7 @@ jobs:
|
||||||
cmake \
|
cmake \
|
||||||
--build ${PWD}/build \
|
--build ${PWD}/build \
|
||||||
--config ${{ env.BUILD_TYPE }} \
|
--config ${{ env.BUILD_TYPE }} \
|
||||||
--parallel 2
|
--parallel ${{ steps.build-cores.outputs.amount }}
|
||||||
|
|
||||||
- name: Install (System Libraries)
|
- name: Install (System Libraries)
|
||||||
if: ${{ runner.os == 'Linux' && matrix.config.compiler != 'mingw' }}
|
if: ${{ runner.os == 'Linux' && matrix.config.compiler != 'mingw' }}
|
||||||
|
@ -180,9 +190,6 @@ jobs:
|
||||||
if [ '${{ matrix.config.compiler }}' == 'msvc' ]; then
|
if [ '${{ matrix.config.compiler }}' == 'msvc' ]; then
|
||||||
CMAKE_EXTRA_ARGS+=('-DCMAKE_GENERATOR_PLATFORM=${{ steps.windows-identify.outputs.msvc-target }}')
|
CMAKE_EXTRA_ARGS+=('-DCMAKE_GENERATOR_PLATFORM=${{ steps.windows-identify.outputs.msvc-target }}')
|
||||||
|
|
||||||
# FIXME We don't want all the MSVC warnings to cause errors yet
|
|
||||||
export USE_WAE=OFF
|
|
||||||
|
|
||||||
# Force static linking
|
# Force static linking
|
||||||
# 1. Make MSVC runtime configurable
|
# 1. Make MSVC runtime configurable
|
||||||
CMAKE_EXTRA_ARGS+=('-DCMAKE_POLICY_DEFAULT_CMP0091=NEW')
|
CMAKE_EXTRA_ARGS+=('-DCMAKE_POLICY_DEFAULT_CMP0091=NEW')
|
||||||
|
@ -211,7 +218,7 @@ jobs:
|
||||||
cmake \
|
cmake \
|
||||||
--build ${PWD}/build \
|
--build ${PWD}/build \
|
||||||
--config ${{ env.BUILD_TYPE }} \
|
--config ${{ env.BUILD_TYPE }} \
|
||||||
--parallel 2
|
--parallel ${{ steps.build-cores.outputs.amount }}
|
||||||
|
|
||||||
- name: Package [Windows]
|
- name: Package [Windows]
|
||||||
if: ${{ runner.os == 'Windows' || matrix.config.compiler == 'mingw' }}
|
if: ${{ runner.os == 'Windows' || matrix.config.compiler == 'mingw' }}
|
||||||
|
|
|
@ -177,6 +177,10 @@ else()
|
||||||
add_subdirectory(extern/SDL EXCLUDE_FROM_ALL)
|
add_subdirectory(extern/SDL EXCLUDE_FROM_ALL)
|
||||||
list(APPEND DEPENDENCIES_INCLUDE_DIRS extern/SDL/include)
|
list(APPEND DEPENDENCIES_INCLUDE_DIRS extern/SDL/include)
|
||||||
list(APPEND DEPENDENCIES_LIBRARIES SDL2-static)
|
list(APPEND DEPENDENCIES_LIBRARIES SDL2-static)
|
||||||
|
# Work around add_subdirectory'd SDL not propagating HAVE_LIBC to MSVC furnace build
|
||||||
|
if (MSVC)
|
||||||
|
list(APPEND DEPENDENCIES_COMPILE_OPTIONS "/DHAVE_LIBC")
|
||||||
|
endif()
|
||||||
message(STATUS "Using vendored SDL2")
|
message(STATUS "Using vendored SDL2")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -457,9 +461,13 @@ if (NOT MSVC)
|
||||||
list(APPEND WARNING_FLAGS -Werror)
|
list(APPEND WARNING_FLAGS -Werror)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
# /wd4100 == -Wno-unused-parameter
|
add_compile_options("/utf-8")
|
||||||
add_compile_options("/source-charset:utf-8")
|
set(WARNING_FLAGS /W2 /D_CRT_SECURE_NO_WARNINGS)
|
||||||
set(WARNING_FLAGS /W4 /wd4100 /D_CRT_SECURE_NO_WARNINGS)
|
list(APPEND WARNING_FLAGS
|
||||||
|
/wd4244 # implicit type conversions
|
||||||
|
/wd4305 # truncations
|
||||||
|
/wd4309 # truncations of constant values
|
||||||
|
)
|
||||||
if (WARNINGS_ARE_ERRORS)
|
if (WARNINGS_ARE_ERRORS)
|
||||||
list(APPEND WARNING_FLAGS /WX)
|
list(APPEND WARNING_FLAGS /WX)
|
||||||
endif()
|
endif()
|
||||||
|
|
16
extern/pfd-fixed/portable-file-dialogs.h
vendored
16
extern/pfd-fixed/portable-file-dialogs.h
vendored
|
@ -1331,6 +1331,14 @@ inline std::string internal::file_dialog::select_folder_vista(IFileDialog *ifd,
|
||||||
|
|
||||||
// notify implementation
|
// notify implementation
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
inline BOOL WINAPI icon_enum_callback(HMODULE hModule, LPCTSTR lpType, LPTSTR lpName, LONG_PTR lParam)
|
||||||
|
{
|
||||||
|
((NOTIFYICONDATAW *)lParam)->hIcon = ::LoadIcon(GetModuleHandle(nullptr), lpName);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
inline notify::notify(std::string const &title,
|
inline notify::notify(std::string const &title,
|
||||||
std::string const &message,
|
std::string const &message,
|
||||||
icon _icon /* = icon::info */)
|
icon _icon /* = icon::info */)
|
||||||
|
@ -1383,14 +1391,8 @@ inline notify::notify(std::string const &title,
|
||||||
/* case icon::info: */ default: nid->dwInfoFlags = NIIF_INFO; break;
|
/* case icon::info: */ default: nid->dwInfoFlags = NIIF_INFO; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ENUMRESNAMEPROC icon_enum_callback = [](HMODULE, LPCTSTR, LPTSTR lpName, LONG_PTR lParam) -> BOOL WINAPI
|
|
||||||
{
|
|
||||||
((NOTIFYICONDATAW *)lParam)->hIcon = ::LoadIcon(GetModuleHandle(nullptr), lpName);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
nid->hIcon = ::LoadIcon(nullptr, IDI_APPLICATION);
|
nid->hIcon = ::LoadIcon(nullptr, IDI_APPLICATION);
|
||||||
::EnumResourceNames(nullptr, RT_GROUP_ICON, icon_enum_callback, (LONG_PTR)nid.get());
|
::EnumResourceNames(nullptr, RT_GROUP_ICON, (ENUMRESNAMEPROC)icon_enum_callback, (LONG_PTR)nid.get());
|
||||||
|
|
||||||
nid->uTimeout = 5000;
|
nid->uTimeout = 5000;
|
||||||
|
|
||||||
|
|
|
@ -319,6 +319,18 @@ class DivDispatch {
|
||||||
*/
|
*/
|
||||||
virtual int getPortaFloor(int ch);
|
virtual int getPortaFloor(int ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the required amplification level of this dispatch's output.
|
||||||
|
* @return the amplification level.
|
||||||
|
*/
|
||||||
|
virtual float getPostAmp();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check whether DC offset correction is required.
|
||||||
|
* @return truth.
|
||||||
|
*/
|
||||||
|
virtual bool getDCOffRequired();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get a description of a dispatch-specific effect.
|
* get a description of a dispatch-specific effect.
|
||||||
* @param effect the effect.
|
* @param effect the effect.
|
||||||
|
|
|
@ -79,6 +79,11 @@ void DivDispatchContainer::flush(size_t count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivDispatchContainer::fillBuf(size_t runtotal, size_t offset, size_t size) {
|
void DivDispatchContainer::fillBuf(size_t runtotal, size_t offset, size_t size) {
|
||||||
|
if (dcOffCompensation && runtotal>0) {
|
||||||
|
dcOffCompensation=false;
|
||||||
|
prevSample[0]=bbIn[0][0];
|
||||||
|
if (dispatch->isStereo()) prevSample[1]=bbIn[1][0];
|
||||||
|
}
|
||||||
if (lowQuality) {
|
if (lowQuality) {
|
||||||
for (size_t i=0; i<runtotal; i++) {
|
for (size_t i=0; i<runtotal; i++) {
|
||||||
temp[0]=bbIn[0][i];
|
temp[0]=bbIn[0][i];
|
||||||
|
@ -126,6 +131,9 @@ void DivDispatchContainer::clear() {
|
||||||
temp[1]=0;
|
temp[1]=0;
|
||||||
prevSample[0]=0;
|
prevSample[0]=0;
|
||||||
prevSample[1]=0;
|
prevSample[1]=0;
|
||||||
|
if (dispatch->getDCOffRequired()) {
|
||||||
|
dcOffCompensation=true;
|
||||||
|
}
|
||||||
// run for one cycle to determine DC offset
|
// run for one cycle to determine DC offset
|
||||||
// TODO: SAA1099 doesn't like that
|
// TODO: SAA1099 doesn't like that
|
||||||
/*dispatch->acquire(bbIn[0],bbIn[1],0,1);
|
/*dispatch->acquire(bbIn[0],bbIn[1],0,1);
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dataErrors.h"
|
|
||||||
#include "song.h"
|
|
||||||
#include <functional>
|
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "instrument.h"
|
#include "instrument.h"
|
||||||
|
@ -873,6 +870,11 @@ void DivEngine::play() {
|
||||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
keyHit[i]=false;
|
keyHit[i]=false;
|
||||||
}
|
}
|
||||||
|
if (output) if (!skipping && output->midiOut!=NULL) {
|
||||||
|
int pos=totalTicksR/6;
|
||||||
|
output->midiOut->send(TAMidiMessage(TA_MIDI_POSITION,(pos>>7)&0x7f,pos&0x7f));
|
||||||
|
output->midiOut->send(TAMidiMessage(TA_MIDI_MACHINE_PLAY,0,0));
|
||||||
|
}
|
||||||
BUSY_END;
|
BUSY_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,6 +920,14 @@ void DivEngine::stop() {
|
||||||
for (int i=0; i<song.systemLen; i++) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
disCont[i].dispatch->notifyPlaybackStop();
|
disCont[i].dispatch->notifyPlaybackStop();
|
||||||
}
|
}
|
||||||
|
if (output) if (output->midiOut!=NULL) {
|
||||||
|
output->midiOut->send(TAMidiMessage(TA_MIDI_MACHINE_STOP,0,0));
|
||||||
|
for (int i=0; i<chans; i++) {
|
||||||
|
if (chan[i].curMidiNote>=0) {
|
||||||
|
output->midiOut->send(TAMidiMessage(0x80|(i&15),chan[i].curMidiNote,0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BUSY_END;
|
BUSY_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,8 @@ struct DivChannelState {
|
||||||
bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff;
|
bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff;
|
||||||
bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, noteOnInhibit, resetArp;
|
bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, noteOnInhibit, resetArp;
|
||||||
|
|
||||||
int midiNote, curMidiNote;
|
int midiNote, curMidiNote, midiPitch;
|
||||||
|
bool midiAftertouch;
|
||||||
|
|
||||||
DivChannelState():
|
DivChannelState():
|
||||||
note(-1),
|
note(-1),
|
||||||
|
@ -130,7 +131,9 @@ struct DivChannelState {
|
||||||
noteOnInhibit(false),
|
noteOnInhibit(false),
|
||||||
resetArp(false),
|
resetArp(false),
|
||||||
midiNote(-1),
|
midiNote(-1),
|
||||||
curMidiNote(-1) {}
|
curMidiNote(-1),
|
||||||
|
midiPitch(-1),
|
||||||
|
midiAftertouch(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DivNoteEvent {
|
struct DivNoteEvent {
|
||||||
|
@ -151,7 +154,7 @@ struct DivDispatchContainer {
|
||||||
int temp[2], prevSample[2];
|
int temp[2], prevSample[2];
|
||||||
short* bbIn[2];
|
short* bbIn[2];
|
||||||
short* bbOut[2];
|
short* bbOut[2];
|
||||||
bool lowQuality;
|
bool lowQuality, dcOffCompensation;
|
||||||
|
|
||||||
void setRates(double gotRate);
|
void setRates(double gotRate);
|
||||||
void setQuality(bool lowQual);
|
void setQuality(bool lowQual);
|
||||||
|
@ -169,7 +172,8 @@ struct DivDispatchContainer {
|
||||||
prevSample{0,0},
|
prevSample{0,0},
|
||||||
bbIn{NULL,NULL},
|
bbIn{NULL,NULL},
|
||||||
bbOut{NULL,NULL},
|
bbOut{NULL,NULL},
|
||||||
lowQuality(false) {}
|
lowQuality(false),
|
||||||
|
dcOffCompensation(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DivEngine {
|
class DivEngine {
|
||||||
|
@ -295,6 +299,7 @@ class DivEngine {
|
||||||
bool keyHit[DIV_MAX_CHANS];
|
bool keyHit[DIV_MAX_CHANS];
|
||||||
float* oscBuf[2];
|
float* oscBuf[2];
|
||||||
float oscSize;
|
float oscSize;
|
||||||
|
int oscReadPos, oscWritePos;
|
||||||
|
|
||||||
void runExportThread();
|
void runExportThread();
|
||||||
void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size);
|
void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size);
|
||||||
|
@ -769,6 +774,8 @@ class DivEngine {
|
||||||
totalProcessed(0),
|
totalProcessed(0),
|
||||||
oscBuf{NULL,NULL},
|
oscBuf{NULL,NULL},
|
||||||
oscSize(1),
|
oscSize(1),
|
||||||
|
oscReadPos(0),
|
||||||
|
oscWritePos(0),
|
||||||
adpcmAMem(NULL),
|
adpcmAMem(NULL),
|
||||||
adpcmAMemLen(0),
|
adpcmAMemLen(0),
|
||||||
adpcmBMem(NULL),
|
adpcmBMem(NULL),
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
|
|
@ -567,12 +567,12 @@ void DivInstrument::putInsData(SafeWriter* w) {
|
||||||
w->writeC(ws.param4);
|
w->writeC(ws.param4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readMacroData(DivInstrumentMacro &m, SafeReader& reader, short version) {
|
DivDataErrors DivInstrument::readMacroData(DivInstrumentMacro& m, SafeReader& reader, short version) {
|
||||||
char magic[4];
|
char magic[4];
|
||||||
reader.read(magic,4);
|
reader.read(magic,4);
|
||||||
if (memcmp(magic,"MACR",4)!=0) {
|
if (memcmp(magic,"MACR",4)!=0) {
|
||||||
logE("invalid macro header!\n");
|
logE("invalid macro header!\n");
|
||||||
return /*DIV_DATA_INVALID_HEADER*/;
|
return DIV_DATA_INVALID_HEADER;
|
||||||
}
|
}
|
||||||
reader.readI();
|
reader.readI();
|
||||||
|
|
||||||
|
@ -591,7 +591,7 @@ void readMacroData(DivInstrumentMacro &m, SafeReader& reader, short version) {
|
||||||
reader.readI(); // reserved
|
reader.readI(); // reserved
|
||||||
reader.readI(); // reserved
|
reader.readI(); // reserved
|
||||||
}
|
}
|
||||||
/*return DIV_DATA_SUCCESS*/;
|
return DIV_DATA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
|
@ -695,65 +695,173 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
for (int k=0; k<14; k++) reader.readC();
|
for (int k=0; k<14; k++) reader.readC();
|
||||||
|
|
||||||
if (istest) {
|
if (istest) {
|
||||||
readMacroData(std.volMacro,reader,version);
|
if (readMacroData(std.volMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.arpMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.dutyMacro,reader,version);
|
}
|
||||||
readMacroData(std.waveMacro,reader,version);
|
if (readMacroData(std.arpMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.pitchMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.ex1Macro,reader,version);
|
}
|
||||||
readMacroData(std.ex2Macro,reader,version);
|
if (readMacroData(std.dutyMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.ex3Macro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.algMacro,reader,version);
|
}
|
||||||
readMacroData(std.fbMacro,reader,version);
|
if (readMacroData(std.waveMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.fmsMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.fms2Macro,reader,version);
|
}
|
||||||
readMacroData(std.amsMacro,reader,version);
|
if (readMacroData(std.pitchMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.ams2Macro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.panLMacro,reader,version);
|
}
|
||||||
readMacroData(std.panRMacro,reader,version);
|
if (readMacroData(std.ex1Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.phaseResetMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.ex4Macro,reader,version);
|
}
|
||||||
readMacroData(std.ex5Macro,reader,version);
|
if (readMacroData(std.ex2Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.ex6Macro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.ex7Macro,reader,version);
|
}
|
||||||
readMacroData(std.ex8Macro,reader,version);
|
if (readMacroData(std.ex3Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.algMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.fbMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.fmsMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.fms2Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.amsMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ams2Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.panLMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.panRMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.phaseResetMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ex4Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ex5Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ex6Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ex7Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ex8Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
// FM macros
|
// FM macros
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
|
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
|
||||||
readMacroData(op.amMacro,reader,version);
|
if (readMacroData(op.amMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(op.arMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(op.drMacro,reader,version);
|
}
|
||||||
readMacroData(op.multMacro,reader,version);
|
if (readMacroData(op.arMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(op.rrMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(op.slMacro,reader,version);
|
}
|
||||||
readMacroData(op.tlMacro,reader,version);
|
if (readMacroData(op.drMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(op.dt2Macro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(op.rsMacro,reader,version);
|
}
|
||||||
readMacroData(op.dtMacro,reader,version);
|
if (readMacroData(op.multMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(op.d2rMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(op.ssgMacro,reader,version);
|
}
|
||||||
readMacroData(op.damMacro,reader,version);
|
if (readMacroData(op.rrMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(op.dvbMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(op.egtMacro,reader,version);
|
}
|
||||||
readMacroData(op.kslMacro,reader,version);
|
if (readMacroData(op.slMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(op.susMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(op.vibMacro,reader,version);
|
}
|
||||||
readMacroData(op.wsMacro,reader,version);
|
if (readMacroData(op.tlMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(op.ksrMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.dt2Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.rsMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.dtMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.d2rMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.ssgMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.damMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.dvbMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.egtMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.kslMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.susMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.vibMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.wsMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(op.ksrMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// wavesynth macros
|
// wavesynth macros
|
||||||
readMacroData(std.ws.wave1Macro,reader,version);
|
if (readMacroData(std.ws.wave1Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.ws.wave2Macro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.ws.rateDividerMacro,reader,version);
|
}
|
||||||
readMacroData(std.ws.effectMacro,reader,version);
|
if (readMacroData(std.ws.wave2Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.ws.oneShotMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.ws.enabledMacro,reader,version);
|
}
|
||||||
readMacroData(std.ws.globalMacro,reader,version);
|
if (readMacroData(std.ws.rateDividerMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.ws.speedMacro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.ws.param1Macro,reader,version);
|
}
|
||||||
readMacroData(std.ws.param2Macro,reader,version);
|
if (readMacroData(std.ws.effectMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
readMacroData(std.ws.param3Macro,reader,version);
|
return DIV_DATA_INVALID_HEADER;
|
||||||
readMacroData(std.ws.param4Macro,reader,version);
|
}
|
||||||
|
if (readMacroData(std.ws.oneShotMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ws.enabledMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ws.globalMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ws.speedMacro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ws.param1Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ws.param2Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ws.param3Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
|
if (readMacroData(std.ws.param4Macro,reader,version)!=DIV_DATA_SUCCESS) {
|
||||||
|
return DIV_DATA_INVALID_HEADER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!istest) {
|
if (!istest) {
|
||||||
// standard
|
// standard
|
||||||
|
@ -882,18 +990,42 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
|
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
|
||||||
reader.readByte(op.amMacro.val,op.amMacro.len,1);
|
for (int l=0; l<op.amMacro.len; l++) {
|
||||||
reader.readByte(op.arMacro.val,op.arMacro.len,1);
|
op.amMacro.val[l]=(unsigned char)reader.readC();
|
||||||
reader.readByte(op.drMacro.val,op.drMacro.len,1);
|
}
|
||||||
reader.readByte(op.multMacro.val,op.multMacro.len,1);
|
for (int l=0; l<op.arMacro.len; l++) {
|
||||||
reader.readByte(op.rrMacro.val,op.rrMacro.len,1);
|
op.arMacro.val[l]=(unsigned char)reader.readC();
|
||||||
reader.readByte(op.slMacro.val,op.slMacro.len,1);
|
}
|
||||||
reader.readByte(op.tlMacro.val,op.tlMacro.len,1);
|
for (int l=0; l<op.drMacro.len; l++) {
|
||||||
reader.readByte(op.dt2Macro.val,op.dt2Macro.len,1);
|
op.drMacro.val[l]=(unsigned char)reader.readC();
|
||||||
reader.readByte(op.rsMacro.val,op.rsMacro.len,1);
|
}
|
||||||
reader.readByte(op.dtMacro.val,op.dtMacro.len,1);
|
for (int l=0; l<op.multMacro.len; l++) {
|
||||||
reader.readByte(op.d2rMacro.val,op.d2rMacro.len,1);
|
op.multMacro.val[l]=(unsigned char)reader.readC();
|
||||||
reader.readByte(op.ssgMacro.val,op.ssgMacro.len,1);
|
}
|
||||||
|
for (int l=0; l<op.rrMacro.len; l++) {
|
||||||
|
op.rrMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.slMacro.len; l++) {
|
||||||
|
op.slMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.tlMacro.len; l++) {
|
||||||
|
op.tlMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.dt2Macro.len; l++) {
|
||||||
|
op.dt2Macro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.rsMacro.len; l++) {
|
||||||
|
op.rsMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.dtMacro.len; l++) {
|
||||||
|
op.dtMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.d2rMacro.len; l++) {
|
||||||
|
op.d2rMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.ssgMacro.len; l++) {
|
||||||
|
op.ssgMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -974,14 +1106,30 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) {
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
|
DivInstrumentSTD::OpMacro& op=std.opMacros[i];
|
||||||
reader.readByte(op.damMacro.val,op.damMacro.len,1);
|
for (int l=0; l<op.damMacro.len; l++) {
|
||||||
reader.readByte(op.dvbMacro.val,op.dvbMacro.len,1);
|
op.damMacro.val[l]=(unsigned char)reader.readC();
|
||||||
reader.readByte(op.egtMacro.val,op.egtMacro.len,1);
|
}
|
||||||
reader.readByte(op.kslMacro.val,op.kslMacro.len,1);
|
for (int l=0; l<op.dvbMacro.len; l++) {
|
||||||
reader.readByte(op.susMacro.val,op.susMacro.len,1);
|
op.dvbMacro.val[l]=(unsigned char)reader.readC();
|
||||||
reader.readByte(op.vibMacro.val,op.vibMacro.len,1);
|
}
|
||||||
reader.readByte(op.wsMacro.val,op.wsMacro.len,1);
|
for (int l=0; l<op.egtMacro.len; l++) {
|
||||||
reader.readByte(op.ksrMacro.val,op.ksrMacro.len,1);
|
op.egtMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.kslMacro.len; l++) {
|
||||||
|
op.kslMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.susMacro.len; l++) {
|
||||||
|
op.susMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.vibMacro.len; l++) {
|
||||||
|
op.vibMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.wsMacro.len; l++) {
|
||||||
|
op.wsMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
|
for (int l=0; l<op.ksrMacro.len; l++) {
|
||||||
|
op.ksrMacro.val[l]=(unsigned char)reader.readC();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -437,7 +437,7 @@ struct DivInstrument {
|
||||||
* @param version the format version.
|
* @param version the format version.
|
||||||
* @return a DivDataErrors.
|
* @return a DivDataErrors.
|
||||||
*/
|
*/
|
||||||
void readMacroData(DivInstrumentMacro& m, SafeReader& reader, short version);
|
DivDataErrors readMacroData(DivInstrumentMacro& m, SafeReader& reader, short version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* save this instrument to a file.
|
* save this instrument to a file.
|
||||||
|
|
|
@ -62,134 +62,84 @@ void DivMacroInt::release() {
|
||||||
|
|
||||||
void DivMacroInt::init(DivInstrument* which) {
|
void DivMacroInt::init(DivInstrument* which) {
|
||||||
ins=which;
|
ins=which;
|
||||||
macroList.clear();
|
// initialize
|
||||||
// initialize common macros
|
while (!macroList.empty()) {
|
||||||
vol.init();
|
macroList.front().init();
|
||||||
arp.init();
|
macroList.pop_front();
|
||||||
duty.init();
|
}
|
||||||
wave.init();
|
|
||||||
pitch.init();
|
|
||||||
ex1.init();
|
|
||||||
ex2.init();
|
|
||||||
ex3.init();
|
|
||||||
alg.init();
|
|
||||||
fb.init();
|
|
||||||
fms.init();
|
|
||||||
ams.init();
|
|
||||||
fms2.init();
|
|
||||||
ams2.init();
|
|
||||||
panL.init();
|
|
||||||
panR.init();
|
|
||||||
phaseReset.init();
|
|
||||||
ex4.init();
|
|
||||||
ex5.init();
|
|
||||||
ex6.init();
|
|
||||||
ex7.init();
|
|
||||||
ex8.init();
|
|
||||||
|
|
||||||
released=false;
|
released=false;
|
||||||
|
|
||||||
// initialize FM operator macro
|
|
||||||
op[0]=IntOp();
|
|
||||||
op[1]=IntOp();
|
|
||||||
op[2]=IntOp();
|
|
||||||
op[3]=IntOp();
|
|
||||||
|
|
||||||
// initialize wavesynth macro
|
|
||||||
ws=IntWS();
|
|
||||||
|
|
||||||
if (ins==NULL) return;
|
if (ins==NULL) return;
|
||||||
|
|
||||||
// prepare common macro
|
// prepare common macro
|
||||||
if (ins->std.volMacro.len>0) {
|
if (ins->std.volMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(vol,ins->std.volMacro));
|
macroList.push_back(DivMacroExecList(vol,ins->std.volMacro));
|
||||||
vol.prepare(&ins->std.volMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.arpMacro.len>0) {
|
if (ins->std.arpMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(arp,ins->std.arpMacro));
|
macroList.push_back(DivMacroExecList(arp,ins->std.arpMacro));
|
||||||
arp.prepare(&ins->std.arpMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.dutyMacro.len>0) {
|
if (ins->std.dutyMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(duty,ins->std.dutyMacro));
|
macroList.push_back(DivMacroExecList(duty,ins->std.dutyMacro));
|
||||||
duty.prepare(&ins->std.dutyMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.waveMacro.len>0) {
|
if (ins->std.waveMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(wave,ins->std.waveMacro));
|
macroList.push_back(DivMacroExecList(wave,ins->std.waveMacro));
|
||||||
wave.prepare(&ins->std.waveMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.pitchMacro.len>0) {
|
if (ins->std.pitchMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(pitch,ins->std.pitchMacro));
|
macroList.push_back(DivMacroExecList(pitch,ins->std.pitchMacro));
|
||||||
pitch.prepare(&ins->std.pitchMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex1Macro.len>0) {
|
if (ins->std.ex1Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex1,ins->std.ex1Macro));
|
macroList.push_back(DivMacroExecList(ex1,ins->std.ex1Macro));
|
||||||
ex1.prepare(&ins->std.ex1Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex2Macro.len>0) {
|
if (ins->std.ex2Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex2,ins->std.ex2Macro));
|
macroList.push_back(DivMacroExecList(ex2,ins->std.ex2Macro));
|
||||||
ex2.prepare(&ins->std.ex2Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex3Macro.len>0) {
|
if (ins->std.ex3Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex3,ins->std.ex3Macro));
|
macroList.push_back(DivMacroExecList(ex3,ins->std.ex3Macro));
|
||||||
ex3.prepare(&ins->std.ex3Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.algMacro.len>0) {
|
if (ins->std.algMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(alg,ins->std.algMacro));
|
macroList.push_back(DivMacroExecList(alg,ins->std.algMacro));
|
||||||
alg.prepare(&ins->std.algMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.fbMacro.len>0) {
|
if (ins->std.fbMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(fb,ins->std.fbMacro));
|
macroList.push_back(DivMacroExecList(fb,ins->std.fbMacro));
|
||||||
fb.prepare(&ins->std.fbMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.fmsMacro.len>0) {
|
if (ins->std.fmsMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(fms,ins->std.fmsMacro));
|
macroList.push_back(DivMacroExecList(fms,ins->std.fmsMacro));
|
||||||
fms.prepare(&ins->std.fmsMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.fms2Macro.len>0) {
|
if (ins->std.fms2Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(fms2,ins->std.fms2Macro));
|
macroList.push_back(DivMacroExecList(fms2,ins->std.fms2Macro));
|
||||||
fms2.prepare(&ins->std.fms2Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.amsMacro.len>0) {
|
if (ins->std.amsMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ams,ins->std.amsMacro));
|
macroList.push_back(DivMacroExecList(ams,ins->std.amsMacro));
|
||||||
ams.prepare(&ins->std.amsMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ams2Macro.len>0) {
|
if (ins->std.ams2Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ams2,ins->std.ams2Macro));
|
macroList.push_back(DivMacroExecList(ams2,ins->std.ams2Macro));
|
||||||
ams2.prepare(&ins->std.ams2Macro);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: other macros
|
// TODO: other macros
|
||||||
if (ins->std.panLMacro.len>0) {
|
if (ins->std.panLMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(panL,ins->std.panLMacro));
|
macroList.push_back(DivMacroExecList(panL,ins->std.panLMacro));
|
||||||
panL.prepare(&ins->std.panLMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.panRMacro.len>0) {
|
if (ins->std.panRMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(panR,ins->std.panRMacro));
|
macroList.push_back(DivMacroExecList(panR,ins->std.panRMacro));
|
||||||
panR.prepare(&ins->std.panRMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.phaseResetMacro.len>0) {
|
if (ins->std.phaseResetMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(phaseReset,ins->std.phaseResetMacro));
|
macroList.push_back(DivMacroExecList(phaseReset,ins->std.phaseResetMacro));
|
||||||
phaseReset.prepare(&ins->std.phaseResetMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex4Macro.len>0) {
|
if (ins->std.ex4Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex4,ins->std.ex4Macro));
|
macroList.push_back(DivMacroExecList(ex4,ins->std.ex4Macro));
|
||||||
ex4.prepare(&ins->std.ex4Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex5Macro.len>0) {
|
if (ins->std.ex5Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex5,ins->std.ex5Macro));
|
macroList.push_back(DivMacroExecList(ex5,ins->std.ex5Macro));
|
||||||
ex5.prepare(&ins->std.ex5Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex6Macro.len>0) {
|
if (ins->std.ex6Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex6,ins->std.ex6Macro));
|
macroList.push_back(DivMacroExecList(ex6,ins->std.ex6Macro));
|
||||||
ex6.prepare(&ins->std.ex6Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex7Macro.len>0) {
|
if (ins->std.ex7Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex7,ins->std.ex7Macro));
|
macroList.push_back(DivMacroExecList(ex7,ins->std.ex7Macro));
|
||||||
ex7.prepare(&ins->std.ex7Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ex8Macro.len>0) {
|
if (ins->std.ex8Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ex8,ins->std.ex8Macro));
|
macroList.push_back(DivMacroExecList(ex8,ins->std.ex8Macro));
|
||||||
ex8.prepare(&ins->std.ex8Macro);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare FM operator macros
|
// prepare FM operator macros
|
||||||
|
@ -198,135 +148,103 @@ void DivMacroInt::init(DivInstrument* which) {
|
||||||
IntOp& o=op[i];
|
IntOp& o=op[i];
|
||||||
if (m.amMacro.len>0) {
|
if (m.amMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.am,m.amMacro));
|
macroList.push_back(DivMacroExecList(o.am,m.amMacro));
|
||||||
o.am.prepare(&m.amMacro);
|
|
||||||
}
|
}
|
||||||
if (m.arMacro.len>0) {
|
if (m.arMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.ar,m.arMacro));
|
macroList.push_back(DivMacroExecList(o.ar,m.arMacro));
|
||||||
o.ar.prepare(&m.arMacro);
|
|
||||||
}
|
}
|
||||||
if (m.drMacro.len>0) {
|
if (m.drMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.dr,m.drMacro));
|
macroList.push_back(DivMacroExecList(o.dr,m.drMacro));
|
||||||
o.dr.prepare(&m.drMacro);
|
|
||||||
}
|
}
|
||||||
if (m.multMacro.len>0) {
|
if (m.multMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.mult,m.multMacro));
|
macroList.push_back(DivMacroExecList(o.mult,m.multMacro));
|
||||||
o.mult.prepare(&m.multMacro);
|
|
||||||
}
|
}
|
||||||
if (m.rrMacro.len>0) {
|
if (m.rrMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.rr,m.rrMacro));
|
macroList.push_back(DivMacroExecList(o.rr,m.rrMacro));
|
||||||
o.rr.prepare(&m.rrMacro);
|
|
||||||
}
|
}
|
||||||
if (m.slMacro.len>0) {
|
if (m.slMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.sl,m.slMacro));
|
macroList.push_back(DivMacroExecList(o.sl,m.slMacro));
|
||||||
o.sl.prepare(&m.slMacro);
|
|
||||||
}
|
}
|
||||||
if (m.tlMacro.len>0) {
|
if (m.tlMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.tl,m.tlMacro));
|
macroList.push_back(DivMacroExecList(o.tl,m.tlMacro));
|
||||||
o.tl.prepare(&m.tlMacro);
|
|
||||||
}
|
}
|
||||||
if (m.dt2Macro.len>0) {
|
if (m.dt2Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.dt2,m.dt2Macro));
|
macroList.push_back(DivMacroExecList(o.dt2,m.dt2Macro));
|
||||||
o.dt2.prepare(&m.dt2Macro);
|
|
||||||
}
|
}
|
||||||
if (m.rsMacro.len>0) {
|
if (m.rsMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.rs,m.rsMacro));
|
macroList.push_back(DivMacroExecList(o.rs,m.rsMacro));
|
||||||
o.rs.prepare(&m.rsMacro);
|
|
||||||
}
|
}
|
||||||
if (m.dtMacro.len>0) {
|
if (m.dtMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.dt,m.dtMacro));
|
macroList.push_back(DivMacroExecList(o.dt,m.dtMacro));
|
||||||
o.dt.prepare(&m.dtMacro);
|
|
||||||
}
|
}
|
||||||
if (m.d2rMacro.len>0) {
|
if (m.d2rMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.d2r,m.d2rMacro));
|
macroList.push_back(DivMacroExecList(o.d2r,m.d2rMacro));
|
||||||
o.d2r.prepare(&m.d2rMacro);
|
|
||||||
}
|
}
|
||||||
if (m.ssgMacro.len>0) {
|
if (m.ssgMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.ssg,m.ssgMacro));
|
macroList.push_back(DivMacroExecList(o.ssg,m.ssgMacro));
|
||||||
o.ssg.prepare(&m.ssgMacro);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.damMacro.len>0) {
|
if (m.damMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.dam,m.damMacro));
|
macroList.push_back(DivMacroExecList(o.dam,m.damMacro));
|
||||||
o.dam.prepare(&m.damMacro);
|
|
||||||
}
|
}
|
||||||
if (m.dvbMacro.len>0) {
|
if (m.dvbMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.dvb,m.dvbMacro));
|
macroList.push_back(DivMacroExecList(o.dvb,m.dvbMacro));
|
||||||
o.dvb.prepare(&m.dvbMacro);
|
|
||||||
}
|
}
|
||||||
if (m.egtMacro.len>0) {
|
if (m.egtMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.egt,m.egtMacro));
|
macroList.push_back(DivMacroExecList(o.egt,m.egtMacro));
|
||||||
o.egt.prepare(&m.egtMacro);
|
|
||||||
}
|
}
|
||||||
if (m.kslMacro.len>0) {
|
if (m.kslMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.ksl,m.kslMacro));
|
macroList.push_back(DivMacroExecList(o.ksl,m.kslMacro));
|
||||||
o.ksl.prepare(&m.kslMacro);
|
|
||||||
}
|
}
|
||||||
if (m.susMacro.len>0) {
|
if (m.susMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.sus,m.susMacro));
|
macroList.push_back(DivMacroExecList(o.sus,m.susMacro));
|
||||||
o.sus.prepare(&m.susMacro);
|
|
||||||
}
|
}
|
||||||
if (m.vibMacro.len>0) {
|
if (m.vibMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.vib,m.vibMacro));
|
macroList.push_back(DivMacroExecList(o.vib,m.vibMacro));
|
||||||
o.vib.prepare(&m.vibMacro);
|
|
||||||
}
|
}
|
||||||
if (m.wsMacro.len>0) {
|
if (m.wsMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.ws,m.wsMacro));
|
macroList.push_back(DivMacroExecList(o.ws,m.wsMacro));
|
||||||
o.ws.prepare(&m.wsMacro);
|
|
||||||
}
|
}
|
||||||
if (m.ksrMacro.len>0) {
|
if (m.ksrMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(o.ksr,m.ksrMacro));
|
macroList.push_back(DivMacroExecList(o.ksr,m.ksrMacro));
|
||||||
o.ksr.prepare(&m.ksrMacro);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare wavesynth macros
|
// prepare wavesynth macros
|
||||||
if (ins->std.ws.wave1Macro.len>0) {
|
if (ins->std.ws.wave1Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.wave1,ins->std.ws.wave1Macro));
|
macroList.push_back(DivMacroExecList(ws.wave1,ins->std.ws.wave1Macro));
|
||||||
ws.wave1.prepare(&ins->std.ws.wave1Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.wave2Macro.len>0) {
|
if (ins->std.ws.wave2Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.wave2,ins->std.ws.wave2Macro));
|
macroList.push_back(DivMacroExecList(ws.wave2,ins->std.ws.wave2Macro));
|
||||||
ws.wave2.prepare(&ins->std.ws.wave2Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.rateDividerMacro.len>0) {
|
if (ins->std.ws.rateDividerMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.rateDivider,ins->std.ws.rateDividerMacro));
|
macroList.push_back(DivMacroExecList(ws.rateDivider,ins->std.ws.rateDividerMacro));
|
||||||
ws.rateDivider.prepare(&ins->std.ws.rateDividerMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.effectMacro.len>0) {
|
if (ins->std.ws.effectMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.effect,ins->std.ws.effectMacro));
|
macroList.push_back(DivMacroExecList(ws.effect,ins->std.ws.effectMacro));
|
||||||
ws.effect.prepare(&ins->std.ws.effectMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.oneShotMacro.len>0) {
|
if (ins->std.ws.oneShotMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.oneShot,ins->std.ws.oneShotMacro));
|
macroList.push_back(DivMacroExecList(ws.oneShot,ins->std.ws.oneShotMacro));
|
||||||
ws.oneShot.prepare(&ins->std.ws.oneShotMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.enabledMacro.len>0) {
|
if (ins->std.ws.enabledMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.enabled,ins->std.ws.enabledMacro));
|
macroList.push_back(DivMacroExecList(ws.enabled,ins->std.ws.enabledMacro));
|
||||||
ws.enabled.prepare(&ins->std.ws.enabledMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.globalMacro.len>0) {
|
if (ins->std.ws.globalMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.global,ins->std.ws.globalMacro));
|
macroList.push_back(DivMacroExecList(ws.global,ins->std.ws.globalMacro));
|
||||||
ws.global.prepare(&ins->std.ws.globalMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.speedMacro.len>0) {
|
if (ins->std.ws.speedMacro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.speed,ins->std.ws.speedMacro));
|
macroList.push_back(DivMacroExecList(ws.speed,ins->std.ws.speedMacro));
|
||||||
ws.speed.prepare(&ins->std.ws.speedMacro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.param1Macro.len>0) {
|
if (ins->std.ws.param1Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.param1,ins->std.ws.param1Macro));
|
macroList.push_back(DivMacroExecList(ws.param1,ins->std.ws.param1Macro));
|
||||||
ws.param1.prepare(&ins->std.ws.param1Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.param2Macro.len>0) {
|
if (ins->std.ws.param2Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.param2,ins->std.ws.param2Macro));
|
macroList.push_back(DivMacroExecList(ws.param2,ins->std.ws.param2Macro));
|
||||||
ws.param2.prepare(&ins->std.ws.param2Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.param3Macro.len>0) {
|
if (ins->std.ws.param3Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.param3,ins->std.ws.param3Macro));
|
macroList.push_back(DivMacroExecList(ws.param3,ins->std.ws.param3Macro));
|
||||||
ws.param3.prepare(&ins->std.ws.param3Macro);
|
|
||||||
}
|
}
|
||||||
if (ins->std.ws.param4Macro.len>0) {
|
if (ins->std.ws.param4Macro.len>0) {
|
||||||
macroList.push_back(DivMacroExecList(ws.param4,ins->std.ws.param4Macro));
|
macroList.push_back(DivMacroExecList(ws.param4,ins->std.ws.param4Macro));
|
||||||
ws.param4.prepare(&ins->std.ws.param4Macro);
|
|
||||||
}
|
}
|
||||||
if (!macroList.empty()) {
|
if (!macroList.empty()) {
|
||||||
for (std::list<DivMacroExecList>::iterator iter = macroList.begin(); iter!= macroList.end(); iter++) {
|
for (std::list<DivMacroExecList>::iterator iter = macroList.begin(); iter!= macroList.end(); iter++) {
|
||||||
|
|
|
@ -24,26 +24,20 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
struct DivMacroStruct {
|
struct DivMacroStruct {
|
||||||
DivInstrumentMacro* source;
|
|
||||||
int pos;
|
int pos;
|
||||||
int val;
|
int val;
|
||||||
bool has, had, finished, will;
|
bool has, had, finished, will;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
void doMacro(DivInstrumentMacro& source, bool released);
|
void doMacro(DivInstrumentMacro& source, bool released);
|
||||||
void init() {
|
void init() {
|
||||||
source=NULL;
|
|
||||||
pos=mode=0;
|
pos=mode=0;
|
||||||
has=had=will=false;
|
has=had=will=false;
|
||||||
}
|
}
|
||||||
void prepare(DivInstrumentMacro* s) {
|
void prepare(DivInstrumentMacro& source) {
|
||||||
if (s!=NULL) {
|
|
||||||
source=s;
|
|
||||||
has=had=will=true;
|
has=had=will=true;
|
||||||
mode=source->mode;
|
mode=source.mode;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DivMacroStruct():
|
DivMacroStruct():
|
||||||
source(NULL),
|
|
||||||
pos(0),
|
pos(0),
|
||||||
val(0),
|
val(0),
|
||||||
has(false),
|
has(false),
|
||||||
|
@ -56,8 +50,11 @@ struct DivMacroStruct {
|
||||||
struct DivMacroExecList {
|
struct DivMacroExecList {
|
||||||
DivMacroStruct& macro;
|
DivMacroStruct& macro;
|
||||||
DivInstrumentMacro& source;
|
DivInstrumentMacro& source;
|
||||||
|
void init() {
|
||||||
|
macro.init();
|
||||||
|
}
|
||||||
void prepare() {
|
void prepare() {
|
||||||
macro.prepare(&source);
|
macro.prepare(source);
|
||||||
}
|
}
|
||||||
void doMacro(bool released) {
|
void doMacro(bool released) {
|
||||||
macro.doMacro(source, released);
|
macro.doMacro(source, released);
|
||||||
|
@ -155,6 +152,7 @@ class DivMacroInt {
|
||||||
|
|
||||||
DivMacroInt():
|
DivMacroInt():
|
||||||
ins(NULL),
|
ins(NULL),
|
||||||
|
macroList(),
|
||||||
released(false),
|
released(false),
|
||||||
vol(),
|
vol(),
|
||||||
arp(),
|
arp(),
|
||||||
|
|
|
@ -74,6 +74,14 @@ int DivDispatch::getPortaFloor(int ch) {
|
||||||
return 0x00;
|
return 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float DivDispatch::getPostAmp() {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DivDispatch::getDCOffRequired() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const char* DivDispatch::getEffectName(unsigned char effect) {
|
const char* DivDispatch::getEffectName(unsigned char effect) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -497,6 +497,10 @@ void DivPlatformAY8910::flushWrites() {
|
||||||
while (!writes.empty()) writes.pop();
|
while (!writes.empty()) writes.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivPlatformAY8910::getDCOffRequired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformAY8910::reset() {
|
void DivPlatformAY8910::reset() {
|
||||||
while (!writes.empty()) writes.pop();
|
while (!writes.empty()) writes.pop();
|
||||||
ay->device_reset();
|
ay->device_reset();
|
||||||
|
|
|
@ -95,6 +95,7 @@ class DivPlatformAY8910: public DivDispatch {
|
||||||
void setFlags(unsigned int flags);
|
void setFlags(unsigned int flags);
|
||||||
bool isStereo();
|
bool isStereo();
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
|
bool getDCOffRequired();
|
||||||
void notifyInsDeletion(void* ins);
|
void notifyInsDeletion(void* ins);
|
||||||
void poke(unsigned int addr, unsigned short val);
|
void poke(unsigned int addr, unsigned short val);
|
||||||
void poke(std::vector<DivRegWrite>& wlist);
|
void poke(std::vector<DivRegWrite>& wlist);
|
||||||
|
|
|
@ -123,7 +123,7 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
}
|
}
|
||||||
while (!writes.empty()) {
|
while (!writes.empty()) {
|
||||||
QueuedWrite w=writes.front();
|
QueuedWrite w=writes.front();
|
||||||
if (bank!=(w.addr>>4)) {
|
if ((int)bank!=(w.addr>>4)) {
|
||||||
bank=w.addr>>4;
|
bank=w.addr>>4;
|
||||||
ay->address_w(0x0d);
|
ay->address_w(0x0d);
|
||||||
ay->data_w(0xa0|(bank<<4)|ayEnvMode[0]);
|
ay->data_w(0xa0|(bank<<4)|ayEnvMode[0]);
|
||||||
|
|
|
@ -118,7 +118,7 @@ void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
void DivPlatformC64::updateFilter() {
|
void DivPlatformC64::updateFilter() {
|
||||||
rWrite(0x15,filtCut&7);
|
rWrite(0x15,filtCut&7);
|
||||||
rWrite(0x16,filtCut>>3);
|
rWrite(0x16,filtCut>>3);
|
||||||
rWrite(0x17,(filtRes<<4)|(chan[2].filter<<2)|(chan[1].filter<<1)|(chan[0].filter));
|
rWrite(0x17,(filtRes<<4)|(chan[2].filter<<2)|(chan[1].filter<<1)|(int)(chan[0].filter));
|
||||||
rWrite(0x18,(filtControl<<4)|vol);
|
rWrite(0x18,(filtControl<<4)|vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ void DivPlatformC64::tick() {
|
||||||
}
|
}
|
||||||
if (chan[i].std.wave.had) {
|
if (chan[i].std.wave.had) {
|
||||||
chan[i].wave=chan[i].std.wave.val;
|
chan[i].wave=chan[i].std.wave.val;
|
||||||
rWrite(i*7+4,(isMuted[i]?8:(chan[i].wave<<4))|(chan[i].ring<<2)|(chan[i].sync<<1)|chan[i].active);
|
rWrite(i*7+4,(isMuted[i]?8:(chan[i].wave<<4))|(chan[i].ring<<2)|(chan[i].sync<<1)|(int)(chan[i].active));
|
||||||
}
|
}
|
||||||
if (chan[i].std.ex1.had) {
|
if (chan[i].std.ex1.had) {
|
||||||
filtControl=chan[i].std.ex1.val&15;
|
filtControl=chan[i].std.ex1.val&15;
|
||||||
|
@ -232,7 +232,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
||||||
}
|
}
|
||||||
if (chan[c.chan].insChanged) {
|
if (chan[c.chan].insChanged) {
|
||||||
chan[c.chan].wave=(ins->c64.noiseOn<<3)|(ins->c64.pulseOn<<2)|(ins->c64.sawOn<<1)|(ins->c64.triOn);
|
chan[c.chan].wave=(ins->c64.noiseOn<<3)|(ins->c64.pulseOn<<2)|(ins->c64.sawOn<<1)|(int)(ins->c64.triOn);
|
||||||
chan[c.chan].attack=ins->c64.a;
|
chan[c.chan].attack=ins->c64.a;
|
||||||
chan[c.chan].decay=(ins->c64.s==15)?0:ins->c64.d;
|
chan[c.chan].decay=(ins->c64.s==15)?0:ins->c64.d;
|
||||||
chan[c.chan].sustain=ins->c64.s;
|
chan[c.chan].sustain=ins->c64.s;
|
||||||
|
@ -245,7 +245,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
if (ins->c64.initFilter) {
|
if (ins->c64.initFilter) {
|
||||||
filtCut=ins->c64.cut;
|
filtCut=ins->c64.cut;
|
||||||
filtRes=ins->c64.res;
|
filtRes=ins->c64.res;
|
||||||
filtControl=ins->c64.lp|(ins->c64.bp<<1)|(ins->c64.hp<<2)|(ins->c64.ch3off<<3);
|
filtControl=(int)(ins->c64.lp)|(ins->c64.bp<<1)|(ins->c64.hp<<2)|(ins->c64.ch3off<<3);
|
||||||
}
|
}
|
||||||
updateFilter();
|
updateFilter();
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_WAVE:
|
case DIV_CMD_WAVE:
|
||||||
chan[c.chan].wave=c.value;
|
chan[c.chan].wave=c.value;
|
||||||
rWrite(c.chan*7+4,(isMuted[c.chan]?8:(chan[c.chan].wave<<4))|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|chan[c.chan].active);
|
rWrite(c.chan*7+4,(isMuted[c.chan]?8:(chan[c.chan].wave<<4))|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO:
|
case DIV_CMD_LEGATO:
|
||||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
||||||
|
@ -411,11 +411,11 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
chan[c.chan].ring=c.value;
|
chan[c.chan].ring=c.value;
|
||||||
rWrite(c.chan*7+4,(isMuted[c.chan]?8:(chan[c.chan].wave<<4))|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|chan[c.chan].active);
|
rWrite(c.chan*7+4,(isMuted[c.chan]?8:(chan[c.chan].wave<<4))|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
chan[c.chan].sync=c.value;
|
chan[c.chan].sync=c.value;
|
||||||
rWrite(c.chan*7+4,(isMuted[c.chan]?8:(chan[c.chan].wave<<4))|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|chan[c.chan].active);
|
rWrite(c.chan*7+4,(isMuted[c.chan]?8:(chan[c.chan].wave<<4))|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active));
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
filtControl&=7;
|
filtControl&=7;
|
||||||
|
@ -434,7 +434,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
|
|
||||||
void DivPlatformC64::muteChannel(int ch, bool mute) {
|
void DivPlatformC64::muteChannel(int ch, bool mute) {
|
||||||
isMuted[ch]=mute;
|
isMuted[ch]=mute;
|
||||||
rWrite(ch*7+4,(isMuted[ch]?8:(chan[ch].wave<<4))|(chan[ch].ring<<2)|(chan[ch].sync<<1)|chan[ch].active);
|
rWrite(ch*7+4,(isMuted[ch]?8:(chan[ch].wave<<4))|(chan[ch].ring<<2)|(chan[ch].sync<<1)|(int)(chan[ch].active));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformC64::forceIns() {
|
void DivPlatformC64::forceIns() {
|
||||||
|
|
|
@ -89,7 +89,6 @@ void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len
|
||||||
if (!isMuted[2]) {
|
if (!isMuted[2]) {
|
||||||
sample+=mmc5->pcm.output*2;
|
sample+=mmc5->pcm.output*2;
|
||||||
}
|
}
|
||||||
sample=(sample-128)<<6;
|
|
||||||
if (sample>32767) sample=32767;
|
if (sample>32767) sample=32767;
|
||||||
if (sample<-32768) sample=-32768;
|
if (sample<-32768) sample=-32768;
|
||||||
bufL[i]=sample;
|
bufL[i]=sample;
|
||||||
|
@ -336,6 +335,10 @@ int DivPlatformMMC5::getRegisterPoolSize() {
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float DivPlatformMMC5::getPostAmp() {
|
||||||
|
return 64.0f;
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformMMC5::reset() {
|
void DivPlatformMMC5::reset() {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
chan[i]=DivPlatformMMC5::Channel();
|
chan[i]=DivPlatformMMC5::Channel();
|
||||||
|
|
|
@ -74,6 +74,7 @@ class DivPlatformMMC5: public DivDispatch {
|
||||||
void tick();
|
void tick();
|
||||||
void muteChannel(int ch, bool mute);
|
void muteChannel(int ch, bool mute);
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
|
float getPostAmp();
|
||||||
void setFlags(unsigned int flags);
|
void setFlags(unsigned int flags);
|
||||||
void notifyInsDeletion(void* ins);
|
void notifyInsDeletion(void* ins);
|
||||||
void poke(unsigned int addr, unsigned short val);
|
void poke(unsigned int addr, unsigned short val);
|
||||||
|
|
|
@ -80,7 +80,14 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
DivSample* s=parent->getSample(dacSample);
|
DivSample* s=parent->getSample(dacSample);
|
||||||
if (s->samples>0) {
|
if (s->samples>0) {
|
||||||
if (!isMuted[4]) {
|
if (!isMuted[4]) {
|
||||||
rWrite(0x4011,((unsigned char)s->data8[dacPos]+0x80)>>1);
|
unsigned char next=((unsigned char)s->data8[dacPos]+0x80)>>1;
|
||||||
|
if (dacAntiClickOn && dacAntiClick<next) {
|
||||||
|
dacAntiClick+=8;
|
||||||
|
rWrite(0x4011,dacAntiClick);
|
||||||
|
} else {
|
||||||
|
dacAntiClickOn=false;
|
||||||
|
rWrite(0x4011,next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (++dacPos>=s->samples) {
|
if (++dacPos>=s->samples) {
|
||||||
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
if (s->loopStart>=0 && s->loopStart<(int)s->samples) {
|
||||||
|
@ -101,7 +108,7 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
if (nes->apu.clocked) {
|
if (nes->apu.clocked) {
|
||||||
nes->apu.clocked=false;
|
nes->apu.clocked=false;
|
||||||
}
|
}
|
||||||
int sample=(pulse_output(nes)+tnd_output(nes)-128)<<7;
|
int sample=(pulse_output(nes)+tnd_output(nes));
|
||||||
if (sample>32767) sample=32767;
|
if (sample>32767) sample=32767;
|
||||||
if (sample<-32768) sample=-32768;
|
if (sample<-32768) sample=-32768;
|
||||||
bufL[i]=sample;
|
bufL[i]=sample;
|
||||||
|
@ -454,6 +461,10 @@ int DivPlatformNES::getRegisterPoolSize() {
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float DivPlatformNES::getPostAmp() {
|
||||||
|
return 128.0f;
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformNES::reset() {
|
void DivPlatformNES::reset() {
|
||||||
for (int i=0; i<5; i++) {
|
for (int i=0; i<5; i++) {
|
||||||
chan[i]=DivPlatformNES::Channel();
|
chan[i]=DivPlatformNES::Channel();
|
||||||
|
@ -476,6 +487,9 @@ void DivPlatformNES::reset() {
|
||||||
rWrite(0x4015,0x1f);
|
rWrite(0x4015,0x1f);
|
||||||
rWrite(0x4001,chan[0].sweep);
|
rWrite(0x4001,chan[0].sweep);
|
||||||
rWrite(0x4005,chan[1].sweep);
|
rWrite(0x4005,chan[1].sweep);
|
||||||
|
|
||||||
|
dacAntiClickOn=true;
|
||||||
|
dacAntiClick=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivPlatformNES::keyOffAffectsArp(int ch) {
|
bool DivPlatformNES::keyOffAffectsArp(int ch) {
|
||||||
|
|
|
@ -54,10 +54,11 @@ class DivPlatformNES: public DivDispatch {
|
||||||
Channel chan[5];
|
Channel chan[5];
|
||||||
bool isMuted[5];
|
bool isMuted[5];
|
||||||
int dacPeriod, dacRate;
|
int dacPeriod, dacRate;
|
||||||
unsigned int dacPos;
|
unsigned int dacPos, dacAntiClick;
|
||||||
int dacSample;
|
int dacSample;
|
||||||
unsigned char sampleBank;
|
unsigned char sampleBank;
|
||||||
unsigned char apuType;
|
unsigned char apuType;
|
||||||
|
bool dacAntiClickOn;
|
||||||
struct NESAPU* nes;
|
struct NESAPU* nes;
|
||||||
unsigned char regPool[128];
|
unsigned char regPool[128];
|
||||||
|
|
||||||
|
@ -74,6 +75,7 @@ class DivPlatformNES: public DivDispatch {
|
||||||
void tick();
|
void tick();
|
||||||
void muteChannel(int ch, bool mute);
|
void muteChannel(int ch, bool mute);
|
||||||
bool keyOffAffectsArp(int ch);
|
bool keyOffAffectsArp(int ch);
|
||||||
|
float getPostAmp();
|
||||||
void setFlags(unsigned int flags);
|
void setFlags(unsigned int flags);
|
||||||
void notifyInsDeletion(void* ins);
|
void notifyInsDeletion(void* ins);
|
||||||
void poke(unsigned int addr, unsigned short val);
|
void poke(unsigned int addr, unsigned short val);
|
||||||
|
|
|
@ -371,7 +371,7 @@ void DivPlatformOPL::tick() {
|
||||||
if (update4OpMask) {
|
if (update4OpMask) {
|
||||||
update4OpMask=false;
|
update4OpMask=false;
|
||||||
if (oplType==3) {
|
if (oplType==3) {
|
||||||
unsigned char opMask=chan[0].fourOp|(chan[2].fourOp<<1)|(chan[4].fourOp<<2)|(chan[6].fourOp<<3)|(chan[8].fourOp<<4)|(chan[10].fourOp<<5);
|
unsigned char opMask=(int)(chan[0].fourOp)|(chan[2].fourOp<<1)|(chan[4].fourOp<<2)|(chan[6].fourOp<<3)|(chan[8].fourOp<<4)|(chan[10].fourOp<<5);
|
||||||
immWrite(0x104,opMask);
|
immWrite(0x104,opMask);
|
||||||
//printf("updating opMask to %.2x\n",opMask);
|
//printf("updating opMask to %.2x\n",opMask);
|
||||||
}
|
}
|
||||||
|
|
|
@ -620,7 +620,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_EXTCH:
|
case DIV_CMD_FM_EXTCH:
|
||||||
if (!properDrumsSys) break;
|
if (!properDrumsSys) break;
|
||||||
if (properDrums==c.value) break;
|
if ((int)properDrums==c.value) break;
|
||||||
if (c.value) {
|
if (c.value) {
|
||||||
properDrums=true;
|
properDrums=true;
|
||||||
immWrite(0x0e,0x20);
|
immWrite(0x0e,0x20);
|
||||||
|
|
|
@ -414,6 +414,16 @@ void DivPlatformSAA1099::reset() {
|
||||||
|
|
||||||
extMode=false;
|
extMode=false;
|
||||||
|
|
||||||
|
rWrite(8,255);
|
||||||
|
rWrite(9,255);
|
||||||
|
rWrite(10,255);
|
||||||
|
rWrite(11,255);
|
||||||
|
rWrite(12,255);
|
||||||
|
rWrite(13,255);
|
||||||
|
rWrite(16,0x77);
|
||||||
|
rWrite(17,0x77);
|
||||||
|
rWrite(18,0x77);
|
||||||
|
rWrite(0x1c,2);
|
||||||
rWrite(0x1c,1);
|
rWrite(0x1c,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1120,7 +1120,7 @@ void ay8910_device::sound_stream_update(short** outputs, int outLen)
|
||||||
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
for (int chan = 0; chan < NUM_CHANNELS; chan++)
|
||||||
{
|
{
|
||||||
tone = &m_tone[chan];
|
tone = &m_tone[chan];
|
||||||
m_vol_enabled[chan] = (tone->output | tone_enable(chan)) & (noise_output() | noise_enable(chan));
|
m_vol_enabled[chan] = (tone->output | (unsigned char)tone_enable(chan)) & (noise_output() | (unsigned char)noise_enable(chan));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update envelope */
|
/* update envelope */
|
||||||
|
|
|
@ -213,7 +213,8 @@ void apu_turn_on(struct NESAPU* a, BYTE apu_type) {
|
||||||
a->S2.sweep.delay = 1;
|
a->S2.sweep.delay = 1;
|
||||||
a->S2.sweep.divider = 1;
|
a->S2.sweep.divider = 1;
|
||||||
a->TR.frequency = 1;
|
a->TR.frequency = 1;
|
||||||
a->TR.sequencer = 0;
|
/* questo era 0 ma produce click nell'audio */
|
||||||
|
a->TR.sequencer = 7;
|
||||||
a->NS.frequency = 1;
|
a->NS.frequency = 1;
|
||||||
a->NS.shift = 1;
|
a->NS.shift = 1;
|
||||||
a->DMC.frequency = 1;
|
a->DMC.frequency = 1;
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "blip_buf.h"
|
|
||||||
#include "song.h"
|
|
||||||
#include "wavetable.h"
|
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
@ -201,16 +198,24 @@ int DivEngine::dispatchCmd(DivCommand c) {
|
||||||
chan[c.chan].curMidiNote=-1;
|
chan[c.chan].curMidiNote=-1;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_INSTRUMENT:
|
case DIV_CMD_INSTRUMENT:
|
||||||
|
if (chan[c.chan].lastIns!=c.value) {
|
||||||
output->midiOut->send(TAMidiMessage(0xc0|(c.chan&15),c.value,0));
|
output->midiOut->send(TAMidiMessage(0xc0|(c.chan&15),c.value,0));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_VOLUME:
|
case DIV_CMD_VOLUME:
|
||||||
//output->midiOut->send(TAMidiMessage(0xb0|(c.chan&15),0x07,scaledVol));
|
if (chan[c.chan].curMidiNote>=0 && chan[c.chan].midiAftertouch) {
|
||||||
|
chan[c.chan].midiAftertouch=false;
|
||||||
|
output->midiOut->send(TAMidiMessage(0xa0|(c.chan&15),chan[c.chan].curMidiNote,scaledVol));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_PITCH: {
|
case DIV_CMD_PITCH: {
|
||||||
int pitchBend=8192+(c.value<<5);
|
int pitchBend=8192+(c.value<<5);
|
||||||
if (pitchBend<0) pitchBend=0;
|
if (pitchBend<0) pitchBend=0;
|
||||||
if (pitchBend>16383) pitchBend=16383;
|
if (pitchBend>16383) pitchBend=16383;
|
||||||
|
if (pitchBend!=chan[c.chan].midiPitch) {
|
||||||
|
chan[c.chan].midiPitch=pitchBend;
|
||||||
output->midiOut->send(TAMidiMessage(0xe0|(c.chan&15),pitchBend&0x7f,pitchBend>>7));
|
output->midiOut->send(TAMidiMessage(0xe0|(c.chan&15),pitchBend&0x7f,pitchBend>>7));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -963,6 +968,9 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
// volume
|
// volume
|
||||||
if (pat->data[whatRow][3]!=-1) {
|
if (pat->data[whatRow][3]!=-1) {
|
||||||
if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[whatRow][3]) {
|
if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[whatRow][3]) {
|
||||||
|
if (pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0) {
|
||||||
|
chan[i].midiAftertouch=true;
|
||||||
|
}
|
||||||
chan[i].volume=pat->data[whatRow][3]<<8;
|
chan[i].volume=pat->data[whatRow][3]<<8;
|
||||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||||
}
|
}
|
||||||
|
@ -1436,6 +1444,11 @@ bool DivEngine::nextTick(bool noAccum) {
|
||||||
cycles++;
|
cycles++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MIDI clock
|
||||||
|
if (output) if (!skipping && output->midiOut!=NULL) {
|
||||||
|
output->midiOut->send(TAMidiMessage(TA_MIDI_CLOCK,0,0));
|
||||||
|
}
|
||||||
|
|
||||||
while (!pendingNotes.empty()) {
|
while (!pendingNotes.empty()) {
|
||||||
DivNoteEvent& note=pendingNotes.front();
|
DivNoteEvent& note=pendingNotes.front();
|
||||||
if (note.on) {
|
if (note.on) {
|
||||||
|
@ -1732,8 +1745,11 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
|
|
||||||
if (!playing) {
|
if (!playing) {
|
||||||
if (out!=NULL) {
|
if (out!=NULL) {
|
||||||
memcpy(oscBuf[0],out[0],size*sizeof(float));
|
for (unsigned int i=0; i<size; i++) {
|
||||||
memcpy(oscBuf[1],out[1],size*sizeof(float));
|
oscBuf[0][oscWritePos]=out[0][i];
|
||||||
|
oscBuf[1][oscWritePos]=out[1][i];
|
||||||
|
if (++oscWritePos>=32768) oscWritePos=0;
|
||||||
|
}
|
||||||
oscSize=size;
|
oscSize=size;
|
||||||
}
|
}
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
|
@ -1847,6 +1863,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
for (int i=0; i<song.systemLen; i++) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
float volL=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127-(int)song.systemPan[i])/127.0f)*song.masterVol;
|
float volL=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127-(int)song.systemPan[i])/127.0f)*song.masterVol;
|
||||||
float volR=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127+(int)song.systemPan[i])/127.0f)*song.masterVol;
|
float volR=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127+(int)song.systemPan[i])/127.0f)*song.masterVol;
|
||||||
|
volL*=disCont[i].dispatch->getPostAmp();
|
||||||
|
volR*=disCont[i].dispatch->getPostAmp();
|
||||||
if (disCont[i].dispatch->isStereo()) {
|
if (disCont[i].dispatch->isStereo()) {
|
||||||
for (size_t j=0; j<size; j++) {
|
for (size_t j=0; j<size; j++) {
|
||||||
out[0][j]+=((float)disCont[i].bbOut[0][j]/32768.0)*volL;
|
out[0][j]+=((float)disCont[i].bbOut[0][j]/32768.0)*volL;
|
||||||
|
@ -1880,8 +1898,11 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
while (metroPos>=1) metroPos--;
|
while (metroPos>=1) metroPos--;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(oscBuf[0],out[0],size*sizeof(float));
|
for (unsigned int i=0; i<size; i++) {
|
||||||
memcpy(oscBuf[1],out[1],size*sizeof(float));
|
oscBuf[0][oscWritePos]=out[0][i];
|
||||||
|
oscBuf[1][oscWritePos]=out[1][i];
|
||||||
|
if (++oscWritePos>=32768) oscWritePos=0;
|
||||||
|
}
|
||||||
oscSize=size;
|
oscSize=size;
|
||||||
|
|
||||||
if (forceMono) {
|
if (forceMono) {
|
||||||
|
|
|
@ -66,42 +66,6 @@ int SafeReader::read(void* where, size_t count) {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
int SafeReader::readByte(T* where, size_t count, unsigned char byte, Endianness endianness) {
|
|
||||||
if (byte==sizeof(T)) {
|
|
||||||
return read(where,count*byte);
|
|
||||||
} else {
|
|
||||||
#ifdef READ_DEBUG
|
|
||||||
logD("SR: reading %d x %d bit words at %x\n",count,byte<<3,curSeek);
|
|
||||||
#endif
|
|
||||||
if (count==0) return 0;
|
|
||||||
if (curSeek+(count*byte)>len) throw EndOfFileException(this,len);
|
|
||||||
int start,end,inc;
|
|
||||||
switch (endianness) {
|
|
||||||
case BigEndian:
|
|
||||||
start=byte-1;
|
|
||||||
end=-1;
|
|
||||||
inc=-1;
|
|
||||||
break;
|
|
||||||
case LittleEndian:
|
|
||||||
default:
|
|
||||||
start=0;
|
|
||||||
end=byte;
|
|
||||||
inc=1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (int c=0; c<count; c++) {
|
|
||||||
T temp=0;
|
|
||||||
for (int b=start; b!=end; b+=inc) {
|
|
||||||
temp|=(buf[curSeek++]&0xff)<<(b<<3);
|
|
||||||
}
|
|
||||||
*where++=temp;
|
|
||||||
}
|
|
||||||
count*=byte;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
signed char SafeReader::readC() {
|
signed char SafeReader::readC() {
|
||||||
#ifdef READ_DEBUG
|
#ifdef READ_DEBUG
|
||||||
logD("SR: reading char %x:\n",curSeek);
|
logD("SR: reading char %x:\n",curSeek);
|
||||||
|
|
|
@ -51,7 +51,6 @@ class SafeReader {
|
||||||
size_t size();
|
size_t size();
|
||||||
|
|
||||||
int read(void* where, size_t count);
|
int read(void* where, size_t count);
|
||||||
template<typename T> int readByte(T* where, size_t count, unsigned char byte=sizeof(T), Endianness endianness=LittleEndian);
|
|
||||||
|
|
||||||
// these functions may throw EndOfFileException.
|
// these functions may throw EndOfFileException.
|
||||||
signed char readC();
|
signed char readC();
|
||||||
|
|
|
@ -73,39 +73,6 @@ int SafeWriter::write(const void* what, size_t count) {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
int SafeWriter::writeByte(T* what, size_t count, unsigned char byte, Endianness endianness) {
|
|
||||||
if (byte==sizeof(T)) {
|
|
||||||
return write(what,count*byte);
|
|
||||||
} else {
|
|
||||||
if (!operative) return 0;
|
|
||||||
checkSize(count*byte);
|
|
||||||
int start,end,inc;
|
|
||||||
switch (endianness) {
|
|
||||||
case BigEndian:
|
|
||||||
start=byte-1;
|
|
||||||
end=-1;
|
|
||||||
inc=-1;
|
|
||||||
break;
|
|
||||||
case LittleEndian:
|
|
||||||
default:
|
|
||||||
start=0;
|
|
||||||
end=byte;
|
|
||||||
inc=1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (int c=0; c<count; c++) {
|
|
||||||
T temp=*what++;
|
|
||||||
for (int b=start; b!=end; b+=inc) {
|
|
||||||
buf[curSeek++]=(temp>>(byte<<3))&0xff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count*=byte;
|
|
||||||
if (curSeek>len) len=curSeek;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SafeWriter::writeC(signed char val) {
|
int SafeWriter::writeC(signed char val) {
|
||||||
return write(&val,1);
|
return write(&val,1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ class SafeWriter {
|
||||||
size_t size();
|
size_t size();
|
||||||
|
|
||||||
int write(const void* what, size_t count);
|
int write(const void* what, size_t count);
|
||||||
template<typename T> int writeByte(T* what, size_t count, unsigned char byte=sizeof(T), Endianness endianness=LittleEndian);
|
|
||||||
|
|
||||||
int writeC(signed char val);
|
int writeC(signed char val);
|
||||||
int writeS(short val);
|
int writeS(short val);
|
||||||
|
|
|
@ -2600,6 +2600,9 @@ bool FurnaceGUI::loop() {
|
||||||
drawInsList();
|
drawInsList();
|
||||||
drawInsEdit();
|
drawInsEdit();
|
||||||
drawMixer();
|
drawMixer();
|
||||||
|
|
||||||
|
readOsc();
|
||||||
|
|
||||||
drawOsc();
|
drawOsc();
|
||||||
drawVolMeter();
|
drawVolMeter();
|
||||||
drawSettings();
|
drawSettings();
|
||||||
|
@ -3428,7 +3431,10 @@ FurnaceGUI::FurnaceGUI():
|
||||||
openSampleResampleOpt(false),
|
openSampleResampleOpt(false),
|
||||||
openSampleAmplifyOpt(false),
|
openSampleAmplifyOpt(false),
|
||||||
openSampleSilenceOpt(false),
|
openSampleSilenceOpt(false),
|
||||||
openSampleFilterOpt(false) {
|
openSampleFilterOpt(false),
|
||||||
|
oscTotal(0),
|
||||||
|
oscZoom(0.5f),
|
||||||
|
oscZoomSlider(false) {
|
||||||
// value keys
|
// value keys
|
||||||
valueKeys[SDLK_0]=0;
|
valueKeys[SDLK_0]=0;
|
||||||
valueKeys[SDLK_1]=1;
|
valueKeys[SDLK_1]=1;
|
||||||
|
@ -3469,4 +3475,5 @@ FurnaceGUI::FurnaceGUI():
|
||||||
memset(patChanX,0,sizeof(float)*(DIV_MAX_CHANS+1));
|
memset(patChanX,0,sizeof(float)*(DIV_MAX_CHANS+1));
|
||||||
memset(patChanSlideY,0,sizeof(float)*(DIV_MAX_CHANS+1));
|
memset(patChanSlideY,0,sizeof(float)*(DIV_MAX_CHANS+1));
|
||||||
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
|
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
|
||||||
|
memset(oscValues,0,sizeof(float)*512);
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,16 @@ enum FurnaceGUIColors {
|
||||||
GUI_COLOR_FILE_FONT,
|
GUI_COLOR_FILE_FONT,
|
||||||
GUI_COLOR_FILE_OTHER,
|
GUI_COLOR_FILE_OTHER,
|
||||||
|
|
||||||
|
GUI_COLOR_OSC_BG1,
|
||||||
|
GUI_COLOR_OSC_BG2,
|
||||||
|
GUI_COLOR_OSC_BG3,
|
||||||
|
GUI_COLOR_OSC_BG4,
|
||||||
|
GUI_COLOR_OSC_BORDER,
|
||||||
|
GUI_COLOR_OSC_WAVE,
|
||||||
|
GUI_COLOR_OSC_WAVE_PEAK,
|
||||||
|
GUI_COLOR_OSC_REF,
|
||||||
|
GUI_COLOR_OSC_GUIDE,
|
||||||
|
|
||||||
GUI_COLOR_VOLMETER_LOW,
|
GUI_COLOR_VOLMETER_LOW,
|
||||||
GUI_COLOR_VOLMETER_HIGH,
|
GUI_COLOR_VOLMETER_HIGH,
|
||||||
GUI_COLOR_VOLMETER_PEAK,
|
GUI_COLOR_VOLMETER_PEAK,
|
||||||
|
@ -976,6 +986,12 @@ class FurnaceGUI {
|
||||||
size_t sampleClipboardLen;
|
size_t sampleClipboardLen;
|
||||||
bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleSilenceOpt, openSampleFilterOpt;
|
bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleSilenceOpt, openSampleFilterOpt;
|
||||||
|
|
||||||
|
// oscilloscope
|
||||||
|
int oscTotal;
|
||||||
|
float oscValues[512];
|
||||||
|
float oscZoom;
|
||||||
|
bool oscZoomSlider;
|
||||||
|
|
||||||
// visualizer
|
// visualizer
|
||||||
float keyHit[DIV_MAX_CHANS];
|
float keyHit[DIV_MAX_CHANS];
|
||||||
int lastIns[DIV_MAX_CHANS];
|
int lastIns[DIV_MAX_CHANS];
|
||||||
|
@ -996,6 +1012,8 @@ class FurnaceGUI {
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
void prepareLayout();
|
void prepareLayout();
|
||||||
|
|
||||||
|
void readOsc();
|
||||||
|
|
||||||
float calcBPM(int s1, int s2, float hz);
|
float calcBPM(int s1, int s2, float hz);
|
||||||
|
|
||||||
void patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord, const DivPattern** patCache);
|
void patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord, const DivPattern** patCache);
|
||||||
|
|
|
@ -377,6 +377,16 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
|
||||||
D(GUI_COLOR_FILE_FONT,"",ImVec4(0.3f,1.0f,0.6f,1.0f)),
|
D(GUI_COLOR_FILE_FONT,"",ImVec4(0.3f,1.0f,0.6f,1.0f)),
|
||||||
D(GUI_COLOR_FILE_OTHER,"",ImVec4(0.7f,0.7f,0.7f,1.0f)),
|
D(GUI_COLOR_FILE_OTHER,"",ImVec4(0.7f,0.7f,0.7f,1.0f)),
|
||||||
|
|
||||||
|
D(GUI_COLOR_OSC_BG1,"",ImVec4(0.1f,0.18f,0.3f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_BG2,"",ImVec4(0.1f,0.18f,0.3f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_BG3,"",ImVec4(0.05f,0.15f,0.25f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_BG4,"",ImVec4(0.05f,0.15f,0.25f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_BORDER,"",ImVec4(0.4f,0.6f,0.95f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_WAVE,"",ImVec4(0.95f,0.95f,1.0f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_WAVE_PEAK,"",ImVec4(0.95f,0.95f,1.0f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_REF,"",ImVec4(0.3f,0.3f,0.3f,1.0f)),
|
||||||
|
D(GUI_COLOR_OSC_GUIDE,"",ImVec4(0.3,0.3f,0.3f,1.0f)),
|
||||||
|
|
||||||
D(GUI_COLOR_VOLMETER_LOW,"",ImVec4(0.2f,0.6f,0.2f,1.0f)),
|
D(GUI_COLOR_VOLMETER_LOW,"",ImVec4(0.2f,0.6f,0.2f,1.0f)),
|
||||||
D(GUI_COLOR_VOLMETER_HIGH,"",ImVec4(1.0f,0.9f,0.2f,1.0f)),
|
D(GUI_COLOR_VOLMETER_HIGH,"",ImVec4(1.0f,0.9f,0.2f,1.0f)),
|
||||||
D(GUI_COLOR_VOLMETER_PEAK,"",ImVec4(1.0f,0.1f,0.1f,1.0f)),
|
D(GUI_COLOR_VOLMETER_PEAK,"",ImVec4(1.0f,0.1f,0.1f,1.0f)),
|
||||||
|
|
|
@ -1068,7 +1068,7 @@ void FurnaceGUI::drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr,
|
||||||
} \
|
} \
|
||||||
ImGui::SetNextItemWidth(availableWidth); \
|
ImGui::SetNextItemWidth(availableWidth); \
|
||||||
if (ImGui::InputText("##IMacroMML_" macroName,&mmlStr)) { \
|
if (ImGui::InputText("##IMacroMML_" macroName,&mmlStr)) { \
|
||||||
decodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,macroAMin,(bitfield)?((1<<macroAMax)-1):macroAMax,macro.rel); \
|
decodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,macroAMin,(bitfield)?((1<<(bitfield?macroAMax:0))-1):macroAMax,macro.rel); \
|
||||||
} \
|
} \
|
||||||
if (!ImGui::IsItemActive()) { \
|
if (!ImGui::IsItemActive()) { \
|
||||||
encodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,macro.rel); \
|
encodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,macro.rel); \
|
||||||
|
@ -1081,12 +1081,12 @@ void FurnaceGUI::drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr,
|
||||||
ImGui::TableNextColumn(); \
|
ImGui::TableNextColumn(); \
|
||||||
ImGui::Text("%s",displayName); \
|
ImGui::Text("%s",displayName); \
|
||||||
ImGui::SameLine(); \
|
ImGui::SameLine(); \
|
||||||
if (ImGui::SmallButton(displayLoop?(ICON_FA_CHEVRON_UP "##IOPMacro.open_" macroName):(ICON_FA_CHEVRON_DOWN "##IOPMacro.open_" macroName))) { \
|
if (ImGui::SmallButton(displayLoop?(ICON_FA_CHEVRON_UP "##IOPMacroOpen_" macroName):(ICON_FA_CHEVRON_DOWN "##IOPMacroOpen_" macroName))) { \
|
||||||
displayLoop=!displayLoop; \
|
displayLoop=!displayLoop; \
|
||||||
} \
|
} \
|
||||||
if (displayLoop) { \
|
if (displayLoop) { \
|
||||||
ImGui::SetNextItemWidth(lenAvail); \
|
ImGui::SetNextItemWidth(lenAvail); \
|
||||||
if (ImGui::InputScalar("##IOPMacro.len_" #op macroName,ImGuiDataType_U8,¯o.len,&_ONE,&_THREE)) { MARK_MODIFIED \
|
if (ImGui::InputScalar("##IOPMacroLen_" #op macroName,ImGuiDataType_U8,¯o.len,&_ONE,&_THREE)) { MARK_MODIFIED \
|
||||||
if (macro.len>127) macro.len=127; \
|
if (macro.len>127) macro.len=127; \
|
||||||
} \
|
} \
|
||||||
if (macroMode) { \
|
if (macroMode) { \
|
||||||
|
@ -1146,7 +1146,7 @@ void FurnaceGUI::drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr,
|
||||||
processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); \
|
processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); \
|
||||||
} \
|
} \
|
||||||
if (displayLoop) { \
|
if (displayLoop) { \
|
||||||
PlotCustom("##IOPMacro.loop_" #op macroName,loopIndicator,totalFit,macroDragScroll,NULL,0,2,ImVec2(availableWidth,12.0f*dpiScale),sizeof(float),uiColors[GUI_COLOR_MACRO_OTHER],macro.len-macroDragScroll,¯oHoverLoop); \
|
PlotCustom("##IOPMacroLoop_" #op macroName,loopIndicator,totalFit,macroDragScroll,NULL,0,2,ImVec2(availableWidth,12.0f*dpiScale),sizeof(float),uiColors[GUI_COLOR_MACRO_OTHER],macro.len-macroDragScroll,¯oHoverLoop); \
|
||||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { \
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { \
|
||||||
macroLoopDragStart=ImGui::GetItemRectMin(); \
|
macroLoopDragStart=ImGui::GetItemRectMin(); \
|
||||||
macroLoopDragAreaSize=ImVec2(availableWidth,8.0f*dpiScale); \
|
macroLoopDragAreaSize=ImVec2(availableWidth,8.0f*dpiScale); \
|
||||||
|
@ -1168,7 +1168,7 @@ void FurnaceGUI::drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr,
|
||||||
} \
|
} \
|
||||||
ImGui::SetNextItemWidth(availableWidth); \
|
ImGui::SetNextItemWidth(availableWidth); \
|
||||||
if (ImGui::InputText("##IOPMacroMML_" macroName,&mmlStr)) { \
|
if (ImGui::InputText("##IOPMacroMML_" macroName,&mmlStr)) { \
|
||||||
decodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,0,bitfield?((1<<macroHeight)-1):(macroHeight),macro.rel); \
|
decodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,0,bitfield?((1<<(bitfield?macroHeight:0))-1):(macroHeight),macro.rel); \
|
||||||
} \
|
} \
|
||||||
if (!ImGui::IsItemActive()) { \
|
if (!ImGui::IsItemActive()) { \
|
||||||
encodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,macro.rel); \
|
encodeMMLStr(mmlStr,macro.val,macro.len,macro.loop,macro.rel); \
|
||||||
|
|
153
src/gui/osc.cpp
153
src/gui/osc.cpp
|
@ -18,6 +18,52 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include "imgui_internal.h"
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
void FurnaceGUI::readOsc() {
|
||||||
|
int writePos=e->oscWritePos;
|
||||||
|
int readPos=e->oscReadPos;
|
||||||
|
int avail=0;
|
||||||
|
int total=0;
|
||||||
|
if (writePos>=readPos) {
|
||||||
|
avail=writePos-readPos;
|
||||||
|
} else {
|
||||||
|
avail=writePos-readPos+32768;
|
||||||
|
}
|
||||||
|
if (oscTotal==0) {
|
||||||
|
oscTotal=ImGui::GetIO().DeltaTime*e->getAudioDescGot().rate;
|
||||||
|
} else {
|
||||||
|
oscTotal=(oscTotal+(int)round(ImGui::GetIO().DeltaTime*e->getAudioDescGot().rate))>>1;
|
||||||
|
}
|
||||||
|
int bias=avail-oscTotal-e->getAudioDescGot().bufsize;
|
||||||
|
if (bias<0) bias=0;
|
||||||
|
total=oscTotal+(bias>>6);
|
||||||
|
if (total>avail) total=avail;
|
||||||
|
//printf("total: %d. avail: %d bias: %d\n",total,avail,bias);
|
||||||
|
for (int i=0; i<512; i++) {
|
||||||
|
int pos=(readPos+(i*total/512))&0x7fff;
|
||||||
|
oscValues[i]=(e->oscBuf[0][pos]+e->oscBuf[1][pos])*0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float peakDecay=0.05f*60.0f*ImGui::GetIO().DeltaTime;
|
||||||
|
for (int i=0; i<2; i++) {
|
||||||
|
peak[i]*=1.0-peakDecay;
|
||||||
|
if (peak[i]<0.0001) peak[i]=0.0;
|
||||||
|
float newPeak=peak[i];
|
||||||
|
for (int j=0; j<total; j++) {
|
||||||
|
int pos=(readPos+j)&0x7fff;
|
||||||
|
if (fabs(e->oscBuf[i][pos])>newPeak) {
|
||||||
|
newPeak=fabs(e->oscBuf[i][pos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
peak[i]+=(newPeak-peak[i])*0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
readPos=(readPos+total)&0x7fff;
|
||||||
|
e->oscReadPos=readPos;
|
||||||
|
}
|
||||||
|
|
||||||
void FurnaceGUI::drawOsc() {
|
void FurnaceGUI::drawOsc() {
|
||||||
if (nextWindow==GUI_WINDOW_OSCILLOSCOPE) {
|
if (nextWindow==GUI_WINDOW_OSCILLOSCOPE) {
|
||||||
|
@ -27,21 +73,106 @@ void FurnaceGUI::drawOsc() {
|
||||||
}
|
}
|
||||||
if (!oscOpen) return;
|
if (!oscOpen) return;
|
||||||
ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
|
ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0));
|
/*ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));*/
|
||||||
if (ImGui::Begin("Oscilloscope",&oscOpen)) {
|
if (ImGui::Begin("Oscilloscope",&oscOpen)) {
|
||||||
float values[512];
|
if (oscZoomSlider) {
|
||||||
for (int i=0; i<512; i++) {
|
if (ImGui::VSliderFloat("##OscZoom",ImVec2(20.0f*dpiScale,ImGui::GetContentRegionAvail().y),&oscZoom,0.5,2.0)) {
|
||||||
int pos=i*e->oscSize/512;
|
if (oscZoom<0.5) oscZoom=0.5;
|
||||||
values[i]=(e->oscBuf[0][pos]+e->oscBuf[1][pos])*0.5f;
|
if (oscZoom>2.0) oscZoom=2.0;
|
||||||
}
|
}
|
||||||
//ImGui::SetCursorPos(ImVec2(0,0));
|
ImGui::SameLine();
|
||||||
ImGui::BeginDisabled();
|
|
||||||
ImGui::PlotLines("##SingleOsc",values,512,0,NULL,-1.0f,1.0f,ImGui::GetContentRegionAvail());
|
|
||||||
ImGui::EndDisabled();
|
|
||||||
}
|
}
|
||||||
ImGui::PopStyleVar(3);
|
|
||||||
|
ImDrawList* dl=ImGui::GetWindowDrawList();
|
||||||
|
ImGuiWindow* window=ImGui::GetCurrentWindow();
|
||||||
|
|
||||||
|
ImVec2 waveform[512];
|
||||||
|
ImVec2 size=ImGui::GetContentRegionAvail();
|
||||||
|
|
||||||
|
ImVec2 minArea=window->DC.CursorPos;
|
||||||
|
ImVec2 maxArea=ImVec2(
|
||||||
|
minArea.x+size.x,
|
||||||
|
minArea.y+size.y
|
||||||
|
);
|
||||||
|
ImRect rect=ImRect(minArea,maxArea);
|
||||||
|
ImRect inRect=rect;
|
||||||
|
inRect.Min.x+=dpiScale;
|
||||||
|
inRect.Min.y+=dpiScale;
|
||||||
|
inRect.Max.x-=dpiScale;
|
||||||
|
inRect.Max.y-=dpiScale;
|
||||||
|
ImGuiStyle& style=ImGui::GetStyle();
|
||||||
|
ImU32 color=ImGui::GetColorU32(isClipping?uiColors[GUI_COLOR_OSC_WAVE_PEAK]:uiColors[GUI_COLOR_OSC_WAVE]);
|
||||||
|
ImU32 borderColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BORDER]);
|
||||||
|
ImU32 refColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_REF]);
|
||||||
|
ImGui::ItemSize(size,style.FramePadding.y);
|
||||||
|
if (ImGui::ItemAdd(rect,ImGui::GetID("wsDisplay"))) {
|
||||||
|
// https://github.com/ocornut/imgui/issues/3710
|
||||||
|
const int v0 = dl->VtxBuffer.Size;
|
||||||
|
dl->AddRectFilled(inRect.Min,inRect.Max,0xffffffff,8.0f*dpiScale);
|
||||||
|
const int v1 = dl->VtxBuffer.Size;
|
||||||
|
|
||||||
|
for (int i=v0; i<v1; i++) {
|
||||||
|
ImDrawVert* v=&dl->VtxBuffer.Data[i];
|
||||||
|
ImVec4 col0=uiColors[GUI_COLOR_OSC_BG1];
|
||||||
|
ImVec4 col1=uiColors[GUI_COLOR_OSC_BG3];
|
||||||
|
ImVec4 col2=uiColors[GUI_COLOR_OSC_BG2];
|
||||||
|
ImVec4 col3=uiColors[GUI_COLOR_OSC_BG4];
|
||||||
|
|
||||||
|
float shadeX=(v->pos.x-rect.Min.x)/(rect.Max.x-rect.Min.x);
|
||||||
|
float shadeY=(v->pos.y-rect.Min.y)/(rect.Max.y-rect.Min.y);
|
||||||
|
if (shadeX<0.0f) shadeX=0.0f;
|
||||||
|
if (shadeX>1.0f) shadeX=1.0f;
|
||||||
|
if (shadeY<0.0f) shadeY=0.0f;
|
||||||
|
if (shadeY>1.0f) shadeY=1.0f;
|
||||||
|
|
||||||
|
col0.x+=(col2.x-col0.x)*shadeX;
|
||||||
|
col0.y+=(col2.y-col0.y)*shadeX;
|
||||||
|
col0.z+=(col2.z-col0.z)*shadeX;
|
||||||
|
col0.w+=(col2.w-col0.w)*shadeX;
|
||||||
|
|
||||||
|
col1.x+=(col3.x-col1.x)*shadeX;
|
||||||
|
col1.y+=(col3.y-col1.y)*shadeX;
|
||||||
|
col1.z+=(col3.z-col1.z)*shadeX;
|
||||||
|
col1.w+=(col3.w-col1.w)*shadeX;
|
||||||
|
|
||||||
|
col0.x+=(col1.x-col0.x)*shadeY;
|
||||||
|
col0.y+=(col1.y-col0.y)*shadeY;
|
||||||
|
col0.z+=(col1.z-col0.z)*shadeY;
|
||||||
|
col0.w+=(col1.w-col0.w)*shadeY;
|
||||||
|
|
||||||
|
ImVec4 conv=ImGui::ColorConvertU32ToFloat4(v->col);
|
||||||
|
col0.x*=conv.x;
|
||||||
|
col0.y*=conv.y;
|
||||||
|
col0.z*=conv.z;
|
||||||
|
col0.w*=conv.w;
|
||||||
|
|
||||||
|
v->col=ImGui::ColorConvertFloat4ToU32(col0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dl->AddLine(
|
||||||
|
ImLerp(rect.Min,rect.Max,ImVec2(0.0f,0.5f)),
|
||||||
|
ImLerp(rect.Min,rect.Max,ImVec2(0.0f,0.5f)),
|
||||||
|
refColor,
|
||||||
|
dpiScale
|
||||||
|
);
|
||||||
|
|
||||||
|
for (size_t i=0; i<512; i++) {
|
||||||
|
float x=(float)i/512.0f;
|
||||||
|
float y=oscValues[i]*oscZoom;
|
||||||
|
if (y<-0.5f) y=-0.5f;
|
||||||
|
if (y>0.5f) y=0.5f;
|
||||||
|
waveform[i]=ImLerp(rect.Min,rect.Max,ImVec2(x,0.5f-y));
|
||||||
|
}
|
||||||
|
dl->AddPolyline(waveform,512,color,ImDrawFlags_None,dpiScale);
|
||||||
|
dl->AddRect(rect.Min,rect.Max,borderColor,8.0f*dpiScale,0,2.0f*dpiScale);
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||||
|
oscZoomSlider=!oscZoomSlider;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//ImGui::PopStyleVar(3);
|
||||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_OSCILLOSCOPE;
|
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_OSCILLOSCOPE;
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
|
@ -17,8 +17,6 @@
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <SDL_timer.h>
|
|
||||||
#include <imgui.h>
|
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
|
@ -284,27 +282,33 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
||||||
sprintf(id,"..##PE%d_%d_%d",k,i,j);
|
sprintf(id,"..##PE%d_%d_%d",k,i,j);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,inactiveColor);
|
ImGui::PushStyleColor(ImGuiCol_Text,inactiveColor);
|
||||||
} else {
|
} else {
|
||||||
sprintf(id,"%.2X##PE%d_%d_%d",pat->data[i][index],k,i,j);
|
if (pat->data[i][index]>0xff) {
|
||||||
if (pat->data[i][index]<0x10) {
|
sprintf(id,"??##PE%d_%d_%d",k,i,j);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[fxColors[pat->data[i][index]]]);
|
|
||||||
} else if (pat->data[i][index]<0x20) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
|
|
||||||
} else if (pat->data[i][index]<0x30) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]);
|
|
||||||
} else if (pat->data[i][index]<0x48) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
|
|
||||||
} else if (pat->data[i][index]<0x90) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
|
|
||||||
} else if (pat->data[i][index]<0xa0) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_MISC]);
|
|
||||||
} else if (pat->data[i][index]<0xc0) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
|
|
||||||
} else if (pat->data[i][index]<0xd0) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SPEED]);
|
|
||||||
} else if (pat->data[i][index]<0xe0) {
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
|
||||||
} else {
|
} else {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[extFxColors[pat->data[i][index]-0xe0]]);
|
const unsigned char data=pat->data[i][index];
|
||||||
|
sprintf(id,"%.2X##PE%d_%d_%d",data,k,i,j);
|
||||||
|
if (data<0x10) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[fxColors[data]]);
|
||||||
|
} else if (data<0x20) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
|
||||||
|
} else if (data<0x30) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]);
|
||||||
|
} else if (data<0x48) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
|
||||||
|
} else if (data<0x90) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
|
||||||
|
} else if (data<0xa0) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_MISC]);
|
||||||
|
} else if (data<0xc0) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
|
||||||
|
} else if (data<0xd0) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SPEED]);
|
||||||
|
} else if (data<0xe0) {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
|
||||||
|
} else {
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[extFxColors[data-0xe0]]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::SameLine(0.0f,0.0f);
|
ImGui::SameLine(0.0f,0.0f);
|
||||||
|
|
|
@ -942,6 +942,18 @@ void FurnaceGUI::drawSettings() {
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_FILE_OTHER,"Other");
|
UI_COLOR_CONFIG(GUI_COLOR_FILE_OTHER,"Other");
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
if (ImGui::TreeNode("Oscilloscope")) {
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_BORDER,"Border");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_BG1,"Background (top-left)");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_BG2,"Background (top-right)");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_BG3,"Background (bottom-left)");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_BG4,"Background (bottom-right)");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_WAVE,"Waveform");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_WAVE_PEAK,"Waveform (clip)");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_REF,"Reference");
|
||||||
|
UI_COLOR_CONFIG(GUI_COLOR_OSC_GUIDE,"Guide");
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
if (ImGui::TreeNode("Volume Meter")) {
|
if (ImGui::TreeNode("Volume Meter")) {
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_VOLMETER_LOW,"Low");
|
UI_COLOR_CONFIG(GUI_COLOR_VOLMETER_LOW,"Low");
|
||||||
UI_COLOR_CONFIG(GUI_COLOR_VOLMETER_HIGH,"High");
|
UI_COLOR_CONFIG(GUI_COLOR_VOLMETER_HIGH,"High");
|
||||||
|
|
|
@ -284,7 +284,7 @@ void FurnaceGUI::drawSysConf(int i) {
|
||||||
}
|
}
|
||||||
sysPal=flags&1;
|
sysPal=flags&1;
|
||||||
if (ImGui::Checkbox("PAL",&sysPal)) {
|
if (ImGui::Checkbox("PAL",&sysPal)) {
|
||||||
e->setSysFlags(i,(flags&(~1))|sysPal,restart);
|
e->setSysFlags(i,(flags&(~1))|(unsigned int)sysPal,restart);
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
}
|
}
|
||||||
bool bypassLimits=flags&4;
|
bool bypassLimits=flags&4;
|
||||||
|
|
|
@ -49,17 +49,9 @@ void FurnaceGUI::drawVolMeter() {
|
||||||
ImGuiStyle& style=ImGui::GetStyle();
|
ImGuiStyle& style=ImGui::GetStyle();
|
||||||
ImGui::ItemSize(ImVec2(4.0f,4.0f),style.FramePadding.y);
|
ImGui::ItemSize(ImVec2(4.0f,4.0f),style.FramePadding.y);
|
||||||
ImU32 lowColor=ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_LOW]);
|
ImU32 lowColor=ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_LOW]);
|
||||||
float peakDecay=0.05f*60.0f*ImGui::GetIO().DeltaTime;
|
|
||||||
if (ImGui::ItemAdd(rect,ImGui::GetID("volMeter"))) {
|
if (ImGui::ItemAdd(rect,ImGui::GetID("volMeter"))) {
|
||||||
ImGui::RenderFrame(rect.Min,rect.Max,ImGui::GetColorU32(ImGuiCol_FrameBg),true,style.FrameRounding);
|
ImGui::RenderFrame(rect.Min,rect.Max,ImGui::GetColorU32(ImGuiCol_FrameBg),true,style.FrameRounding);
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
peak[i]*=1.0-peakDecay;
|
|
||||||
if (peak[i]<0.0001) peak[i]=0.0;
|
|
||||||
for (int j=0; j<e->oscSize; j++) {
|
|
||||||
if (fabs(e->oscBuf[i][j])>peak[i]) {
|
|
||||||
peak[i]=fabs(e->oscBuf[i][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float logPeak=(20*log10(peak[i])/36.0);
|
float logPeak=(20*log10(peak[i])/36.0);
|
||||||
if (logPeak==NAN) logPeak=0.0;
|
if (logPeak==NAN) logPeak=0.0;
|
||||||
if (logPeak<-1.0) logPeak=-1.0;
|
if (logPeak<-1.0) logPeak=-1.0;
|
||||||
|
|
Loading…
Reference in a new issue