From efab9a80567daba91d6bd7c679d120002d05b9f4 Mon Sep 17 00:00:00 2001 From: Fefa Date: Sun, 4 Jul 2021 23:13:51 +0100 Subject: [PATCH 01/13] Initial VST support for macOS. --- CMakeLists.txt | 5 + Data/Info.plist.in | 34 ++ Data/resourcestr.h | 7 + Vsts/CMakeLists.txt | 66 +++- Vsts/Specimen/SpecimenEditor.cpp | 291 +++++++++++------- Vsts/Specimen/SpecimenEditor.h | 11 +- Vsts/Thunder/ThunderEditor.cpp | 286 +++++++++++------ Vsts/Thunder/ThunderEditor.h | 10 +- WaveSabreCore/CMakeLists.txt | 4 +- .../include/WaveSabreCore/Specimen.h | 14 + WaveSabreCore/include/WaveSabreCore/Thunder.h | 15 +- .../include/WaveSabreCore/Win32defs.h | 23 ++ WaveSabreCore/src/GmDls.cpp | 24 +- WaveSabreCore/src/Specimen.cpp | 70 ++++- WaveSabreCore/src/Thunder.cpp | 70 ++++- WaveSabreVstLib/CMakeLists.txt | 7 + WaveSabreVstLib/src/ImageManager.cpp | 6 + 17 files changed, 717 insertions(+), 226 deletions(-) create mode 100644 Data/Info.plist.in create mode 100644 Data/resourcestr.h create mode 100644 WaveSabreCore/include/WaveSabreCore/Win32defs.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d02e504..7546b16e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ project("WaveSabre") +set (CMAKE_CXX_STANDARD 11) cmake_minimum_required(VERSION 3.11) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -11,13 +12,17 @@ endif() set(VSTSDK3_DIR "${CMAKE_SOURCE_DIR}/Vst3.x/" CACHE PATH "VSTSDK location") # shared code +if(MSVC) add_subdirectory(MSVCRT) +endif() add_subdirectory(WaveSabreCore) +if(MSVC) add_subdirectory(WaveSabrePlayerLib) # binaries add_subdirectory(Tests/PlayerTest) add_subdirectory(WaveSabreStandAlonePlayer) +endif() # VSTs if(VSTSDK3_DIR) diff --git a/Data/Info.plist.in b/Data/Info.plist.in new file mode 100644 index 00000000..f61f8fae --- /dev/null +++ b/Data/Info.plist.in @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + CSResourcesFileMapped + + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + + diff --git a/Data/resourcestr.h b/Data/resourcestr.h new file mode 100644 index 00000000..5ffd4883 --- /dev/null +++ b/Data/resourcestr.h @@ -0,0 +1,7 @@ +/* For using CResourceDescription(const char* name) instead of CResourceDescription(int id). */ + +#define IDB_PNG1 "background.png" +#define IDB_PNG2 "knob1.png" +#define IDB_PNG3 "tinybutton.png" +#define IDB_PNG4 "optionmenu-unpressed.png" +#define IDB_PNG5 "optionmenu-pressed.png" diff --git a/Vsts/CMakeLists.txt b/Vsts/CMakeLists.txt index 323d34e6..f65b207e 100644 --- a/Vsts/CMakeLists.txt +++ b/Vsts/CMakeLists.txt @@ -1,18 +1,68 @@ set(VSTDIR "" CACHE PATH "VST system directory") +find_path(LIBGSM_INCLUDE_DIR NAMES gsm.h + PATHS + /usr/local/include/gsm + /usr/local/include + /usr/include/gsm + /usr/include + ) + +find_library(LIBGSM_LIBRARY NAMES gsm + PATHS + /usr/local/lib + /usr/lib + ) + +if(LIBGSM_INCLUDE_DIR AND LIBGSM_LIBRARY) + add_definitions(-DHAVE_LIBGSM) +endif(LIBGSM_INCLUDE_DIR AND LIBGSM_LIBRARY) + +if(APPLE) + find_library(CARBON_LIBRARY Carbon) + find_library(COCOA_LIBRARY Cocoa) + find_library(AUDIO_TOOLBOX_LIBRARY AudioToolbox) + mark_as_advanced(CARBON_LIBRARY COCOA_LIBRARY) + set(EXTRA_LIBS ${CARBON_LIBRARY} ${COCOA_LIBRARY} ${AUDIO_TOOLBOX_LIBRARY} ${LIBGSM_LIBRARY}) + file(GLOB RESOURCE_FILES ../Data/*.png) +endif(APPLE) + file(GLOB children RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) foreach(child ${children}) if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${child}) file(GLOB sources ${CMAKE_CURRENT_SOURCE_DIR}/${child}/*.h) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/${child} sources) - file(WRITE "${CMAKE_BINARY_DIR}/${child}.def" - "LIBRARY ${child}\nEXPORTS\nVSTPluginMain\nmain=VSTPluginMain") - add_library(${child} SHARED - ${sources} ../Data/data.rc ${CMAKE_BINARY_DIR}/${child}.def) - target_link_libraries(${child} WaveSabreCore WaveSabreVstLib) - set_property(TARGET ${child} APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL - " /LTCG") - set_property(TARGET ${child} PROPERTY FOLDER VSTs) + + if(WIN32) + file(WRITE "${CMAKE_BINARY_DIR}/${child}.def" + "LIBRARY ${child}\nEXPORTS\nVSTPluginMain\nmain=VSTPluginMain") + add_library(${child} SHARED + ${sources} ../Data/data.rc ${CMAKE_BINARY_DIR}/${child}.def) + set_property(TARGET ${child} APPEND_STRING PROPERTY LINK_FLAGS_MINSIZEREL + " /LTCG") + set_property(TARGET ${child} PROPERTY FOLDER VSTs) + endif(WIN32) + + if(APPLE) + add_library(${child} MODULE ${sources} ${RESOURCE_FILES}) + set_target_properties(${child} PROPERTIES + BUNDLE true + BUNDLE_EXTENSION "vst" + XCODE_ATTRIBUTE_WRAPPER_EXTENSION "vst" + MACOSX_BUNDLE_INFO_PLIST "Data/Info.plist.in" + MACOSX_BUNDLE_BUNDLE_NAME "${child}" + MACOSX_BUNDLE_GUI_IDENTIFIER "io.logicoma.wavesabre.${child}" + MACOSX_BUNDLE_ICON_FILE "" + MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0.0" + MACOSX_BUNDLE_COPYRIGHT "Copyright 2012-2021 WaveSabre Team" + XCODE_ATTRIBUTE_USE_HEADERMAP YES + RESOURCE "${RESOURCE_FILES}" + ) + target_include_directories(${child} PUBLIC ${LIBGSM_INCLUDE_DIR}) + target_link_options(${child} PUBLIC "LINKER:-all_load") + endif(APPLE) + + target_link_libraries(${child} WaveSabreCore WaveSabreVstLib ${EXTRA_LIBS}) if(VSTDIR) add_custom_command(TARGET ${child} POST_BUILD diff --git a/Vsts/Specimen/SpecimenEditor.cpp b/Vsts/Specimen/SpecimenEditor.cpp index 084543ae..58d4c81f 100644 --- a/Vsts/Specimen/SpecimenEditor.cpp +++ b/Vsts/Specimen/SpecimenEditor.cpp @@ -9,18 +9,27 @@ using namespace WaveSabreCore; #include using namespace std; +#ifdef _WIN32 #include HACMDRIVERID SpecimenEditor::driverId = NULL; WAVEFORMATEX *SpecimenEditor::foundWaveFormat = nullptr; +#endif + +#ifdef HAVE_LIBGSM +#include +#include + +#define GSM_PACKET_SIZE 160 +#define GSM_MS_PACKET_SIZE (GSM_PACKET_SIZE * 2) +#define GSM_MS_BLOCK_SIZE 65 +#endif SpecimenEditor::SpecimenEditor(AudioEffect *audioEffect) : VstEditor(audioEffect, 580, 400, "SPECIMEN") { pressedTheFuck = false; - fileSelector = nullptr; - specimen = ((SpecimenVst *)audioEffect)->GetSpecimen(); } @@ -30,8 +39,6 @@ SpecimenEditor::~SpecimenEditor() void SpecimenEditor::Open() { - if (!fileSelector) fileSelector = new CFileSelector(nullptr); - addSpacer(); addButton(1000, "LOAD SAMPLE"); addSpacer(); @@ -106,110 +113,183 @@ void SpecimenEditor::setParameter(VstInt32 index, float value) bool oldValue = pressedTheFuck; pressedTheFuck = value != 0.0f; if (pressedTheFuck != oldValue && oldValue) - { - VstFileSelect vfs; - memset(&vfs, 0, sizeof(vfs)); - vfs.command = kVstFileLoad; - vfs.type = kVstFileType; - if (fileSelector->run(&vfs)) - { - try - { - ifstream input(vfs.returnPath, ios::in | ios::binary | ios::ate); - if (!input.is_open()) throw exception("Could not open file."); - auto inputSize = input.tellg(); - auto inputBuf = new unsigned char[(unsigned int)inputSize]; - input.seekg(0, ios::beg); - input.read((char *)inputBuf, inputSize); - input.close(); - - if (*((unsigned int *)inputBuf) != 0x46464952) throw exception("Input file missing RIFF header."); - if (*((unsigned int *)(inputBuf + 4)) != (unsigned int)inputSize - 8) throw exception("Input file contains invalid RIFF header."); - if (*((unsigned int *)(inputBuf + 8)) != 0x45564157) throw exception("Input file missing WAVE chunk."); - - if (*((unsigned int *)(inputBuf + 12)) != 0x20746d66) throw exception("Input file missing format sub-chunk."); - if (*((unsigned int *)(inputBuf + 16)) != 16) throw exception("Input file is not a PCM waveform."); - auto inputFormat = (LPWAVEFORMATEX)(inputBuf + 20); - if (inputFormat->wFormatTag != WAVE_FORMAT_PCM) throw exception("Input file is not a PCM waveform."); - if (inputFormat->nChannels != 1) throw exception("Input file is not mono."); - if (inputFormat->nSamplesPerSec != Specimen::SampleRate) throw exception(("Input file is not " + to_string(Specimen::SampleRate) + "hz.").c_str()); - if (inputFormat->wBitsPerSample != sizeof(short) * 8) throw exception("Input file is not 16-bit."); - - int chunkPos = 36; - int chunkSizeBytes; - while (true) - { - if (chunkPos >= (int)inputSize) throw exception("Input file missing data sub-chunk."); - chunkSizeBytes = *((unsigned int *)(inputBuf + chunkPos + 4)); - if (*((unsigned int *)(inputBuf + chunkPos)) == 0x61746164) break; - else chunkPos += 8 + chunkSizeBytes; - } - int rawDataLength = chunkSizeBytes / 2; - auto rawData = new short[rawDataLength]; - memcpy(rawData, inputBuf + chunkPos + 8, chunkSizeBytes); - - auto compressedData = new char[chunkSizeBytes]; - - int waveFormatSize = 0; - acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &waveFormatSize); - auto waveFormat = (WAVEFORMATEX *)(new char[waveFormatSize]); - memset(waveFormat, 0, waveFormatSize); - waveFormat->wFormatTag = WAVE_FORMAT_GSM610; - waveFormat->nSamplesPerSec = Specimen::SampleRate; - - ACMFORMATCHOOSE formatChoose; - memset(&formatChoose, 0, sizeof(formatChoose)); - formatChoose.cbStruct = sizeof(formatChoose); - formatChoose.pwfx = waveFormat; - formatChoose.cbwfx = waveFormatSize; - formatChoose.pwfxEnum = waveFormat; - formatChoose.fdwEnum = ACM_FORMATENUMF_WFORMATTAG | ACM_FORMATENUMF_NSAMPLESPERSEC; - - if (acmFormatChoose(&formatChoose)) throw exception("acmFormatChoose failed"); - - acmDriverEnum(driverEnumCallback, (DWORD_PTR)waveFormat, NULL); - HACMDRIVER driver = NULL; - if (acmDriverOpen(&driver, driverId, 0)) throw exception("acmDriverOpen failed"); - - HACMSTREAM stream = NULL; - if (acmStreamOpen(&stream, driver, inputFormat, waveFormat, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME)) throw exception("acmStreamOpen failed"); - - ACMSTREAMHEADER streamHeader; - memset(&streamHeader, 0, sizeof(streamHeader)); - streamHeader.cbStruct = sizeof(streamHeader); - streamHeader.pbSrc = (LPBYTE)rawData; - streamHeader.cbSrcLength = chunkSizeBytes; - streamHeader.pbDst = (LPBYTE)compressedData; - streamHeader.cbDstLength = chunkSizeBytes; - if (acmStreamPrepareHeader(stream, &streamHeader, 0)) throw exception("acmStreamPrepareHeader failed"); - if (acmStreamConvert(stream, &streamHeader, 0)) throw exception("acmStreamConvert failed"); - - delete [] rawData; - - acmStreamClose(stream, 0); - acmDriverClose(driver, 0); - - specimen->LoadSample(compressedData, streamHeader.cbDstLengthUsed, chunkSizeBytes, waveFormat); - - delete [] (char *)waveFormat; - - delete [] compressedData; - - delete [] inputBuf; - } - catch (const exception& e) - { - MessageBoxA(0, e.what(), "FUCK THAT SHIT", MB_OK | MB_ICONEXCLAMATION); - } - } - } - } else - { - VstEditor::setParameter(index, value); - } + { + CNewFileSelector* fileSelector = + CNewFileSelector::create(getFrame(), CNewFileSelector::kSelectFile); + if (fileSelector) + { + fileSelector->setDefaultExtension(CFileExtension("WAVE", "wav")); + fileSelector->setTitle("Choose An Audio File"); + fileSelector->run(this); + fileSelector->forget(); + } + } + } + else + { + VstEditor::setParameter(index, value); + } +} +CMessageResult SpecimenEditor::notify(CBaseObject* sender, const char* message) +{ + if (message == CNewFileSelector::kSelectEndMessage) { + CNewFileSelector* sel = dynamic_cast(sender); + if (sel && (sel->getNumSelectedFiles() > 0)) + { + try + { + const char *selectedFile = sel->getSelectedFile(0); + ifstream input(selectedFile, ios::in | ios::binary | ios::ate); + if (!input.is_open()) throw runtime_error("Could not open file."); + auto inputSize = input.tellg(); + auto inputBuf = new unsigned char[(unsigned int)inputSize]; + input.seekg(0, ios::beg); + input.read((char *)inputBuf, inputSize); + input.close(); + + if (*((unsigned int *)inputBuf) != 0x46464952) throw runtime_error("Input file missing RIFF header."); + if (*((unsigned int *)(inputBuf + 4)) != (unsigned int)inputSize - 8) throw runtime_error("Input file contains invalid RIFF header."); + if (*((unsigned int *)(inputBuf + 8)) != 0x45564157) throw runtime_error("Input file missing WAVE chunk."); + + if (*((unsigned int *)(inputBuf + 12)) != 0x20746d66) throw runtime_error("Input file missing format sub-chunk."); + if (*((unsigned int *)(inputBuf + 16)) != 16) throw runtime_error("Input file is not a PCM waveform."); + auto inputFormat = (LPWAVEFORMATEX)(inputBuf + 20); + if (inputFormat->wFormatTag != WAVE_FORMAT_PCM) throw runtime_error("Input file is not a PCM waveform."); + if (inputFormat->nChannels != 1) throw runtime_error("Input file is not mono."); + if (inputFormat->nSamplesPerSec != Specimen::SampleRate) throw runtime_error(("Input file is not " + to_string(Specimen::SampleRate) + "hz.").c_str()); + if (inputFormat->wBitsPerSample != sizeof(short) * 8) throw runtime_error("Input file is not 16-bit."); + + int chunkPos = 36; + int chunkSizeBytes; + while (true) + { + if (chunkPos >= (int)inputSize) throw runtime_error("Input file missing data sub-chunk."); + chunkSizeBytes = *((unsigned int *)(inputBuf + chunkPos + 4)); + if (*((unsigned int *)(inputBuf + chunkPos)) == 0x61746164) break; + else chunkPos += 8 + chunkSizeBytes; + } +#ifdef _WIN32 + int rawDataLength = chunkSizeBytes / 2; + auto rawData = new short[rawDataLength]; + memcpy(rawData, inputBuf + chunkPos + 8, chunkSizeBytes); + + auto compressedData = new char[chunkSizeBytes]; + int waveFormatSize = 0; + acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &waveFormatSize); + auto waveFormat = (WAVEFORMATEX *)(new char[waveFormatSize]); + memset(waveFormat, 0, waveFormatSize); + waveFormat->wFormatTag = WAVE_FORMAT_GSM610; + waveFormat->nSamplesPerSec = Specimen::SampleRate; + + ACMFORMATCHOOSE formatChoose; + memset(&formatChoose, 0, sizeof(formatChoose)); + formatChoose.cbStruct = sizeof(formatChoose); + formatChoose.pwfx = waveFormat; + formatChoose.cbwfx = waveFormatSize; + formatChoose.pwfxEnum = waveFormat; + formatChoose.fdwEnum = ACM_FORMATENUMF_WFORMATTAG | ACM_FORMATENUMF_NSAMPLESPERSEC; + + if (acmFormatChoose(&formatChoose)) throw runtime_error("acmFormatChoose failed"); + + acmDriverEnum(driverEnumCallback, (DWORD_PTR)waveFormat, NULL); + HACMDRIVER driver = NULL; + if (acmDriverOpen(&driver, driverId, 0)) throw runtime_error("acmDriverOpen failed"); + + HACMSTREAM stream = NULL; + if (acmStreamOpen(&stream, driver, inputFormat, waveFormat, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME)) throw runtime_error("acmStreamOpen failed"); + + ACMSTREAMHEADER streamHeader; + memset(&streamHeader, 0, sizeof(streamHeader)); + streamHeader.cbStruct = sizeof(streamHeader); + streamHeader.pbSrc = (LPBYTE)rawData; + streamHeader.cbSrcLength = chunkSizeBytes; + streamHeader.pbDst = (LPBYTE)compressedData; + streamHeader.cbDstLength = chunkSizeBytes; + if (acmStreamPrepareHeader(stream, &streamHeader, 0)) throw runtime_error("acmStreamPrepareHeader failed"); + if (acmStreamConvert(stream, &streamHeader, 0)) throw runtime_error("acmStreamConvert failed"); + + delete [] rawData; + + acmStreamClose(stream, 0); + acmDriverClose(driver, 0); + specimen->LoadSample(compressedData, streamHeader.cbDstLengthUsed, chunkSizeBytes, waveFormat); +#elif HAVE_LIBGSM + int numberOfSamples = chunkSizeBytes / sizeof(gsm_signal); + int numberOfPackets = ((numberOfSamples + GSM_MS_PACKET_SIZE - 1) / GSM_MS_PACKET_SIZE); + int rawDataLength = GSM_MS_PACKET_SIZE * numberOfPackets; + auto rawData = new gsm_signal[rawDataLength]; + memcpy(rawData, inputBuf + chunkPos + 8, chunkSizeBytes); + bzero(rawData + numberOfSamples, sizeof(gsm_signal) * (rawDataLength - numberOfSamples)); + + int compressedSize = GSM_MS_BLOCK_SIZE * numberOfPackets; + auto compressedData = new gsm_byte[compressedSize]; + gsm context = gsm_create(); + + int one = 1; + gsm_option(context, GSM_OPT_WAV49, &one); + + gsm_signal *samples = rawData; + gsm_byte *output = compressedData; + for (int currentPacket = 0; currentPacket < numberOfPackets; currentPacket++) { + gsm_encode(context, samples, output); + gsm_encode(context, samples + GSM_PACKET_SIZE, output + 32); + samples += GSM_MS_PACKET_SIZE; + output += GSM_MS_BLOCK_SIZE; + } + gsm_destroy(context); + + int waveFormatSize = sizeof(GSMWAVEFORMAT); + auto waveFormat = (GSMWAVEFORMAT *)(new char[waveFormatSize]); + memset(waveFormat, 0, waveFormatSize); + waveFormat->wf.wFormatTag = WAVE_FORMAT_GSM610; + waveFormat->wf.nSamplesPerSec = Specimen::SampleRate; + waveFormat->wf.nChannels = 1; + waveFormat->wf.nAvgBytesPerSec = 8957; + waveFormat->wf.nBlockAlign = GSM_MS_BLOCK_SIZE; + waveFormat->wf.cbSize = sizeof(GSMWAVEFORMAT) - sizeof(WAVEFORMATEX); + waveFormat->wSamplesPerPacket = GSM_MS_PACKET_SIZE; + + delete [] rawData; + + specimen->LoadSample((char *) compressedData, compressedSize, chunkSizeBytes, (WAVEFORMATEX *) waveFormat); +#else +#error "Install libgsm so we can GSM encode in Specimen" +#endif + delete [] (char *)waveFormat; + delete [] compressedData; + delete [] inputBuf; + } + catch (const exception& e) + { +#ifdef _WIN32 + MessageBoxA(0, e.what(), "FUCK THAT SHIT", MB_OK | MB_ICONEXCLAMATION); +#endif +#ifdef __APPLE__ + SInt32 nRes = 0; + const void* keys[] = { + kCFUserNotificationAlertHeaderKey, + kCFUserNotificationAlertMessageKey + }; + const void* vals[] = { + CFSTR("FUCK THAT SHIT"), + CFStringCreateWithCString(kCFAllocatorDefault, e.what(), kCFStringEncodingUTF8) + }; + CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFUserNotificationRef notificationRef = CFUserNotificationCreate(kCFAllocatorDefault, 0, kCFUserNotificationPlainAlertLevel, &nRes, dict); + CFRelease(notificationRef); + CFRelease(dict); + CFRelease(vals[1]); +#endif + } + } + } } +#ifdef _WIN32 BOOL __stdcall SpecimenEditor::driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport) { ACMDRIVERDETAILS driverDetails; @@ -248,3 +328,4 @@ BOOL __stdcall SpecimenEditor::formatEnumCallback(HACMDRIVERID driverId, LPACMFO return 1; } +#endif diff --git a/Vsts/Specimen/SpecimenEditor.h b/Vsts/Specimen/SpecimenEditor.h index d9eac7bc..6c33152a 100644 --- a/Vsts/Specimen/SpecimenEditor.h +++ b/Vsts/Specimen/SpecimenEditor.h @@ -7,7 +7,9 @@ using namespace WaveSabreVstLib; #include using namespace WaveSabreCore; -class SpecimenEditor : public VstEditor +#include "vstgui.sf/vstgui/cfileselector.h" + +class SpecimenEditor : public VstEditor, public CBaseObject { public: SpecimenEditor(AudioEffect *audioEffect); @@ -17,17 +19,18 @@ class SpecimenEditor : public VstEditor virtual void setParameter(VstInt32 index, float value); + CMessageResult notify(CBaseObject* sender, const char* message); + private: +#ifdef _WIN32 static BOOL __stdcall driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport); static BOOL __stdcall formatEnumCallback(HACMDRIVERID driverId, LPACMFORMATDETAILS formatDetails, DWORD_PTR dwInstance, DWORD fdwSupport); static HACMDRIVERID driverId; static WAVEFORMATEX *foundWaveFormat; - +#endif bool pressedTheFuck; - CFileSelector *fileSelector; - Specimen *specimen; }; diff --git a/Vsts/Thunder/ThunderEditor.cpp b/Vsts/Thunder/ThunderEditor.cpp index 62f7b816..26c0d9f4 100644 --- a/Vsts/Thunder/ThunderEditor.cpp +++ b/Vsts/Thunder/ThunderEditor.cpp @@ -9,18 +9,27 @@ using namespace WaveSabreCore; #include using namespace std; +#ifdef _WIN32 #include HACMDRIVERID ThunderEditor::driverId = NULL; WAVEFORMATEX *ThunderEditor::foundWaveFormat = nullptr; +#endif + +#ifdef HAVE_LIBGSM +#include +#include + +#define GSM_PACKET_SIZE 160 +#define GSM_MS_PACKET_SIZE (GSM_PACKET_SIZE * 2) +#define GSM_MS_BLOCK_SIZE 65 +#endif ThunderEditor::ThunderEditor(AudioEffect *audioEffect) : VstEditor(audioEffect, 140, 80, "THUNDER") { pressedTheFuck = false; - fileSelector = nullptr; - thunder = ((ThunderVst *)audioEffect)->GetThunder(); } @@ -30,8 +39,6 @@ ThunderEditor::~ThunderEditor() void ThunderEditor::Open() { - if (!fileSelector) fileSelector = new CFileSelector(nullptr); - addSpacer(); addButton(1000, "LOAD SAMPLE"); addSpacer(); @@ -48,105 +55,183 @@ void ThunderEditor::setParameter(VstInt32 index, float value) pressedTheFuck = value != 0.0f; if (pressedTheFuck != oldValue && oldValue) { - VstFileSelect vfs; - memset(&vfs, 0, sizeof(vfs)); - vfs.command = kVstFileLoad; - vfs.type = kVstFileType; - if (fileSelector->run(&vfs)) - { - try - { - ifstream input(vfs.returnPath, ios::in | ios::binary | ios::ate); - if (!input.is_open()) throw exception("Could not open file."); - auto inputSize = input.tellg(); - auto inputBuf = new unsigned char[(unsigned int)inputSize]; - input.seekg(0, ios::beg); - input.read((char *)inputBuf, inputSize); - input.close(); - - if (*((unsigned int *)inputBuf) != 0x46464952) throw exception("Input file missing RIFF header."); - if (*((unsigned int *)(inputBuf + 4)) != (unsigned int)inputSize - 8) throw exception("Input file contains invalid RIFF header."); - if (*((unsigned int *)(inputBuf + 8)) != 0x45564157) throw exception("Input file missing WAVE chunk."); - - if (*((unsigned int *)(inputBuf + 12)) != 0x20746d66) throw exception("Input file missing format sub-chunk."); - if (*((unsigned int *)(inputBuf + 16)) != 16) throw exception("Input file is not a PCM waveform."); - auto inputFormat = (LPWAVEFORMATEX)(inputBuf + 20); - if (inputFormat->wFormatTag != WAVE_FORMAT_PCM) throw exception("Input file is not a PCM waveform."); - if (inputFormat->nChannels != 1) throw exception("Input file is not mono."); - if (inputFormat->nSamplesPerSec != Thunder::SampleRate) throw exception(("Input file is not " + to_string(Thunder::SampleRate) + "hz.").c_str()); - if (inputFormat->wBitsPerSample != sizeof(short) * 8) throw exception("Input file is not 16-bit."); - - int chunkPos = 36; - int chunkSizeBytes; - while (true) - { - if (chunkPos >= (int)inputSize) throw exception("Input file missing data sub-chunk."); - chunkSizeBytes = *((unsigned int *)(inputBuf + chunkPos + 4)); - if (*((unsigned int *)(inputBuf + chunkPos)) == 0x61746164) break; - else chunkPos += 8 + chunkSizeBytes; - } - int rawDataLength = chunkSizeBytes / 2; - auto rawData = new short[rawDataLength]; - memcpy(rawData, inputBuf + chunkPos + 8, chunkSizeBytes); - - auto compressedData = new char[chunkSizeBytes]; - - int waveFormatSize = 0; - acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &waveFormatSize); - auto waveFormat = (WAVEFORMATEX *)(new char[waveFormatSize]); - memset(waveFormat, 0, waveFormatSize); - waveFormat->wFormatTag = WAVE_FORMAT_GSM610; - waveFormat->nSamplesPerSec = Thunder::SampleRate; - - ACMFORMATCHOOSE formatChoose; - memset(&formatChoose, 0, sizeof(formatChoose)); - formatChoose.cbStruct = sizeof(formatChoose); - formatChoose.pwfx = waveFormat; - formatChoose.cbwfx = waveFormatSize; - formatChoose.pwfxEnum = waveFormat; - formatChoose.fdwEnum = ACM_FORMATENUMF_WFORMATTAG | ACM_FORMATENUMF_NSAMPLESPERSEC; - - if (acmFormatChoose(&formatChoose)) throw exception("acmFormatChoose failed"); - - acmDriverEnum(driverEnumCallback, (DWORD_PTR)waveFormat, NULL); - HACMDRIVER driver = NULL; - if (acmDriverOpen(&driver, driverId, 0)) throw exception("acmDriverOpen failed"); - - HACMSTREAM stream = NULL; - if (acmStreamOpen(&stream, driver, inputFormat, waveFormat, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME)) throw exception("acmStreamOpen failed"); - - ACMSTREAMHEADER streamHeader; - memset(&streamHeader, 0, sizeof(streamHeader)); - streamHeader.cbStruct = sizeof(streamHeader); - streamHeader.pbSrc = (LPBYTE)rawData; - streamHeader.cbSrcLength = chunkSizeBytes; - streamHeader.pbDst = (LPBYTE)compressedData; - streamHeader.cbDstLength = chunkSizeBytes; - if (acmStreamPrepareHeader(stream, &streamHeader, 0)) throw exception("acmStreamPrepareHeader failed"); - if (acmStreamConvert(stream, &streamHeader, 0)) throw exception("acmStreamConvert failed"); - - delete [] rawData; - - acmStreamClose(stream, 0); - acmDriverClose(driver, 0); - - thunder->LoadSample(compressedData, streamHeader.cbDstLengthUsed, chunkSizeBytes, waveFormat); - - delete [] (char *)waveFormat; - - delete [] compressedData; - - delete [] inputBuf; - } - catch (const exception& e) - { - MessageBoxA(0, e.what(), "FUCK THAT SHIT", MB_OK | MB_ICONEXCLAMATION); - } - } - } + CNewFileSelector* fileSelector = + CNewFileSelector::create(getFrame(), CNewFileSelector::kSelectFile); + if (fileSelector) + { + fileSelector->setDefaultExtension(CFileExtension("WAVE", "wav")); + fileSelector->setTitle("Choose An Audio File"); + fileSelector->run(this); + fileSelector->forget(); + } + } + } +} + +CMessageResult ThunderEditor::notify(CBaseObject* sender, const char* message) +{ + if (message == CNewFileSelector::kSelectEndMessage) { + CNewFileSelector* sel = dynamic_cast(sender); + if (sel && (sel->getNumSelectedFiles() > 0)) + { + try + { + const char *selectedFile = sel->getSelectedFile(0); + ifstream input(selectedFile, ios::in | ios::binary | ios::ate); + if (!input.is_open()) throw runtime_error("Could not open file."); + auto inputSize = input.tellg(); + auto inputBuf = new unsigned char[(unsigned int)inputSize]; + input.seekg(0, ios::beg); + input.read((char *)inputBuf, inputSize); + input.close(); + + if (*((unsigned int *)inputBuf) != 0x46464952) throw runtime_error("Input file missing RIFF header."); + if (*((unsigned int *)(inputBuf + 4)) != (unsigned int)inputSize - 8) throw runtime_error("Input file contains invalid RIFF header."); + if (*((unsigned int *)(inputBuf + 8)) != 0x45564157) throw runtime_error("Input file missing WAVE chunk."); + + if (*((unsigned int *)(inputBuf + 12)) != 0x20746d66) throw runtime_error("Input file missing format sub-chunk."); + if (*((unsigned int *)(inputBuf + 16)) != 16) throw runtime_error("Input file is not a PCM waveform."); + auto inputFormat = (LPWAVEFORMATEX)(inputBuf + 20); + if (inputFormat->wFormatTag != WAVE_FORMAT_PCM) throw runtime_error("Input file is not a PCM waveform."); + if (inputFormat->nChannels != 1) throw runtime_error("Input file is not mono."); + if (inputFormat->nSamplesPerSec != Thunder::SampleRate) throw runtime_error(("Input file is not " + to_string(Thunder::SampleRate) + "hz.").c_str()); + if (inputFormat->wBitsPerSample != sizeof(short) * 8) throw runtime_error("Input file is not 16-bit."); + + int chunkPos = 36; + int chunkSizeBytes; + while (true) + { + if (chunkPos >= (int)inputSize) throw runtime_error("Input file missing data sub-chunk."); + chunkSizeBytes = *((unsigned int *)(inputBuf + chunkPos + 4)); + if (*((unsigned int *)(inputBuf + chunkPos)) == 0x61746164) break; + else chunkPos += 8 + chunkSizeBytes; + } +#ifdef _WIN32 + int rawDataLength = chunkSizeBytes / 2; + auto rawData = new short[rawDataLength]; + memcpy(rawData, inputBuf + chunkPos + 8, chunkSizeBytes); + + auto compressedData = new char[chunkSizeBytes]; + + int waveFormatSize = 0; + acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &waveFormatSize); + auto waveFormat = (WAVEFORMATEX *)(new char[waveFormatSize]); + memset(waveFormat, 0, waveFormatSize); + waveFormat->wFormatTag = WAVE_FORMAT_GSM610; + waveFormat->nSamplesPerSec = Thunder::SampleRate; + + ACMFORMATCHOOSE formatChoose; + memset(&formatChoose, 0, sizeof(formatChoose)); + formatChoose.cbStruct = sizeof(formatChoose); + formatChoose.pwfx = waveFormat; + formatChoose.cbwfx = waveFormatSize; + formatChoose.pwfxEnum = waveFormat; + formatChoose.fdwEnum = ACM_FORMATENUMF_WFORMATTAG | ACM_FORMATENUMF_NSAMPLESPERSEC; + + if (acmFormatChoose(&formatChoose)) throw runtime_error("acmFormatChoose failed"); + + acmDriverEnum(driverEnumCallback, (DWORD_PTR)waveFormat, NULL); + HACMDRIVER driver = NULL; + if (acmDriverOpen(&driver, driverId, 0)) throw runtime_error("acmDriverOpen failed"); + + HACMSTREAM stream = NULL; + if (acmStreamOpen(&stream, driver, inputFormat, waveFormat, NULL, NULL, NULL, ACM_STREAMOPENF_NONREALTIME)) throw runtime_error("acmStreamOpen failed"); + + ACMSTREAMHEADER streamHeader; + memset(&streamHeader, 0, sizeof(streamHeader)); + streamHeader.cbStruct = sizeof(streamHeader); + streamHeader.pbSrc = (LPBYTE)rawData; + streamHeader.cbSrcLength = chunkSizeBytes; + streamHeader.pbDst = (LPBYTE)compressedData; + streamHeader.cbDstLength = chunkSizeBytes; + if (acmStreamPrepareHeader(stream, &streamHeader, 0)) throw runtime_error("acmStreamPrepareHeader failed"); + if (acmStreamConvert(stream, &streamHeader, 0)) throw runtime_error("acmStreamConvert failed"); + + delete [] rawData; + + acmStreamClose(stream, 0); + acmDriverClose(driver, 0); + + thunder->LoadSample(compressedData, streamHeader.cbDstLengthUsed, chunkSizeBytes, waveFormat); +#elif HAVE_LIBGSM + int numberOfSamples = chunkSizeBytes / sizeof(gsm_signal); + int numberOfPackets = ((numberOfSamples + GSM_MS_PACKET_SIZE - 1) / GSM_MS_PACKET_SIZE); + int rawDataLength = GSM_MS_PACKET_SIZE * numberOfPackets; + auto rawData = new gsm_signal[rawDataLength]; + memcpy(rawData, inputBuf + chunkPos + 8, chunkSizeBytes); + bzero(rawData + numberOfSamples, sizeof(gsm_signal) * (rawDataLength - numberOfSamples)); + + int compressedSize = GSM_MS_BLOCK_SIZE * numberOfPackets; + auto compressedData = new gsm_byte[compressedSize]; + gsm context = gsm_create(); + + int one = 1; + gsm_option(context, GSM_OPT_WAV49, &one); + + gsm_signal *samples = rawData; + gsm_byte *output = compressedData; + for (int currentPacket = 0; currentPacket < numberOfPackets; currentPacket++) { + gsm_encode(context, samples, output); + gsm_encode(context, samples + GSM_PACKET_SIZE, output + 32); + samples += GSM_MS_PACKET_SIZE; + output += GSM_MS_BLOCK_SIZE; + } + gsm_destroy(context); + + int waveFormatSize = sizeof(GSMWAVEFORMAT); + auto waveFormat = (GSMWAVEFORMAT *)(new char[waveFormatSize]); + memset(waveFormat, 0, waveFormatSize); + waveFormat->wf.wFormatTag = WAVE_FORMAT_GSM610; + waveFormat->wf.nSamplesPerSec = Specimen::SampleRate; + waveFormat->wf.nChannels = 1; + waveFormat->wf.nAvgBytesPerSec = 8957; + waveFormat->wf.nBlockAlign = GSM_MS_BLOCK_SIZE; + waveFormat->wf.cbSize = sizeof(GSMWAVEFORMAT) - sizeof(WAVEFORMATEX); + waveFormat->wSamplesPerPacket = GSM_MS_PACKET_SIZE; + + delete [] rawData; + + thunder->LoadSample((char *) compressedData, compressedSize, chunkSizeBytes, (WAVEFORMATEX *) waveFormat); +#else +#error "Install libgsm so we can GSM encode in Thunder" +#endif + delete [] (char *)waveFormat; + + delete [] compressedData; + + delete [] inputBuf; + } + catch (const exception& e) + { +#ifdef _WIN32 + MessageBoxA(0, e.what(), "FUCK THAT SHIT", MB_OK | MB_ICONEXCLAMATION); +#endif +#ifdef __APPLE__ + SInt32 nRes = 0; + const void* keys[] = { + kCFUserNotificationAlertHeaderKey, + kCFUserNotificationAlertMessageKey + }; + const void* vals[] = { + CFSTR("FUCK THAT SHIT"), + CFStringCreateWithCString(kCFAllocatorDefault, e.what(), kCFStringEncodingUTF8) + }; + CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + CFUserNotificationRef notificationRef = CFUserNotificationCreate(kCFAllocatorDefault, 0, kCFUserNotificationPlainAlertLevel, &nRes, dict); + CFRelease(notificationRef); + CFRelease(dict); + CFRelease(vals[1]); +#endif + } + } + return kMessageNotified; } } +#ifdef _WIN32 BOOL __stdcall ThunderEditor::driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport) { ACMDRIVERDETAILS driverDetails; @@ -185,3 +270,4 @@ BOOL __stdcall ThunderEditor::formatEnumCallback(HACMDRIVERID driverId, LPACMFOR return 1; } +#endif diff --git a/Vsts/Thunder/ThunderEditor.h b/Vsts/Thunder/ThunderEditor.h index 6c2c85c7..a26488a2 100644 --- a/Vsts/Thunder/ThunderEditor.h +++ b/Vsts/Thunder/ThunderEditor.h @@ -7,8 +7,9 @@ using namespace WaveSabreVstLib; #include using namespace WaveSabreCore; +#include "vstgui.sf/vstgui/cfileselector.h" -class ThunderEditor : public VstEditor +class ThunderEditor : public VstEditor, public CBaseObject { public: ThunderEditor(AudioEffect *audioEffect); @@ -18,17 +19,18 @@ class ThunderEditor : public VstEditor virtual void setParameter(VstInt32 index, float value); + virtual CMessageResult notify(CBaseObject* sender, const char* message); + private: +#ifdef _WIN32 static BOOL __stdcall driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport); static BOOL __stdcall formatEnumCallback(HACMDRIVERID driverId, LPACMFORMATDETAILS formatDetails, DWORD_PTR dwInstance, DWORD fdwSupport); static HACMDRIVERID driverId; static WAVEFORMATEX *foundWaveFormat; - +#endif bool pressedTheFuck; - CFileSelector *fileSelector; - Thunder *thunder; }; diff --git a/WaveSabreCore/CMakeLists.txt b/WaveSabreCore/CMakeLists.txt index 31ca1e2e..e67acea3 100644 --- a/WaveSabreCore/CMakeLists.txt +++ b/WaveSabreCore/CMakeLists.txt @@ -54,7 +54,9 @@ add_library(WaveSabreCore src/Thunder.cpp src/Twister.cpp) -target_link_libraries(WaveSabreCore Msacm32.lib) +if(WIN32) + target_link_libraries(WaveSabreCore Msacm32.lib) +endif(WIN32) target_include_directories(WaveSabreCore PUBLIC include) if(MSVC) diff --git a/WaveSabreCore/include/WaveSabreCore/Specimen.h b/WaveSabreCore/include/WaveSabreCore/Specimen.h index 86c3d7ec..9cf67f63 100644 --- a/WaveSabreCore/include/WaveSabreCore/Specimen.h +++ b/WaveSabreCore/include/WaveSabreCore/Specimen.h @@ -6,6 +6,7 @@ #include "StateVariableFilter.h" #include "SamplePlayer.h" +#ifdef _WIN32 #include #include @@ -13,6 +14,12 @@ #define _UNICODE #endif #include +#endif + +#ifdef __APPLE__ +#include +#include "Win32defs.h" +#endif namespace WaveSabreCore { @@ -99,10 +106,17 @@ namespace WaveSabreCore float velocity; }; +#ifdef _WIN32 static BOOL __stdcall driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport); static BOOL __stdcall formatEnumCallback(HACMDRIVERID driverId, LPACMFORMATDETAILS formatDetails, DWORD_PTR dwInstance, DWORD fdwSupport); static HACMDRIVERID driverId; +#endif +#ifdef __APPLE__ + static OSStatus callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, + AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, + void *inUserData); +#endif char *chunkData; diff --git a/WaveSabreCore/include/WaveSabreCore/Thunder.h b/WaveSabreCore/include/WaveSabreCore/Thunder.h index 44e5d4b6..583bbc26 100644 --- a/WaveSabreCore/include/WaveSabreCore/Thunder.h +++ b/WaveSabreCore/include/WaveSabreCore/Thunder.h @@ -3,6 +3,7 @@ #include "SynthDevice.h" +#ifdef _WIN32 #include #include @@ -10,6 +11,12 @@ #define _UNICODE #endif #include +#endif + +#ifdef __APPLE__ +#include +#include "Win32defs.h" +#endif namespace WaveSabreCore { @@ -43,11 +50,17 @@ namespace WaveSabreCore int samplePos; }; +#ifdef _WIN32 static BOOL __stdcall driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport); static BOOL __stdcall formatEnumCallback(HACMDRIVERID driverId, LPACMFORMATDETAILS formatDetails, DWORD_PTR dwInstance, DWORD fdwSupport); static HACMDRIVERID driverId; - +#endif +#ifdef __APPLE__ + static OSStatus callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, + AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, + void *inUserData); +#endif char *chunkData; char *waveFormatData; diff --git a/WaveSabreCore/include/WaveSabreCore/Win32defs.h b/WaveSabreCore/include/WaveSabreCore/Win32defs.h new file mode 100644 index 00000000..ebc6326c --- /dev/null +++ b/WaveSabreCore/include/WaveSabreCore/Win32defs.h @@ -0,0 +1,23 @@ +#ifndef __WIN32DEFS_H__ +#define __WIN32DEFS_H__ + +#define WAVE_FORMAT_PCM 1 + +typedef struct __attribute__((packed)) { + uint16_t wFormatTag; + uint16_t nChannels; + uint32_t nSamplesPerSec; + uint32_t nAvgBytesPerSec; + uint16_t nBlockAlign; + uint16_t wBitsPerSample; + uint16_t cbSize; +} WAVEFORMATEX, *LPWAVEFORMATEX; + +#define WAVE_FORMAT_GSM610 49 + +typedef struct __attribute__((packed)) { + WAVEFORMATEX wf; + uint16_t wSamplesPerPacket; +} GSMWAVEFORMAT; + +#endif diff --git a/WaveSabreCore/src/GmDls.cpp b/WaveSabreCore/src/GmDls.cpp index 1ca8e566..b02f4933 100644 --- a/WaveSabreCore/src/GmDls.cpp +++ b/WaveSabreCore/src/GmDls.cpp @@ -1,17 +1,28 @@ #include +#ifdef _WIN32 #include +#endif +#ifdef __APPLE__ +#include +#include +#include +#endif + +#ifdef _WIN32 static char *gmDlsPaths[2] = { "drivers/gm.dls", "drivers/etc/gm.dls" }; +#endif namespace WaveSabreCore { unsigned char *GmDls::Load() { +#ifdef _WIN32 HANDLE gmDlsFile = INVALID_HANDLE_VALUE; for (int i = 0; gmDlsFile == INVALID_HANDLE_VALUE; i++) { @@ -24,7 +35,18 @@ namespace WaveSabreCore unsigned int bytesRead; ReadFile(gmDlsFile, gmDls, gmDlsFileSize, (LPDWORD)&bytesRead, NULL); CloseHandle(gmDlsFile); - +#endif +#ifdef __APPLE__ + glob_t g; + glob("~/Library/Audio/Sounds/Banks/gm.dls", GLOB_TILDE, NULL, &g); + FILE *file = fopen(g.gl_pathv[0], "rb"); + struct stat st; + stat(g.gl_pathv[0], &st); + unsigned char *gmDls = new unsigned char[st.st_size]; + fread(gmDls, 1, st.st_size, file); + fclose(file); + globfree(&g); +#endif return gmDls; } } diff --git a/WaveSabreCore/src/Specimen.cpp b/WaveSabreCore/src/Specimen.cpp index eb0abd88..8bdabd75 100644 --- a/WaveSabreCore/src/Specimen.cpp +++ b/WaveSabreCore/src/Specimen.cpp @@ -3,9 +3,17 @@ #include +#ifdef __APPLE__ +#define GSM_FRAME_SIZE 160 +#define GSM_MS_FRAME_SIZE (GSM_FRAME_SIZE * 2) +#define GSM_MS_BLOCK_SIZE 65 +#endif + namespace WaveSabreCore { +#ifdef _WIN32 HACMDRIVERID Specimen::driverId = NULL; +#endif Specimen::Specimen() : SynthDevice(0) @@ -240,6 +248,7 @@ namespace WaveSabreCore compressedData = new char[compressedSize]; memcpy(compressedData, data, compressedSize); +#ifdef _WIN32 acmDriverEnum(driverEnumCallback, NULL, NULL); HACMDRIVER driver = NULL; acmDriverOpen(&driver, driverId, 0); @@ -272,8 +281,50 @@ namespace WaveSabreCore acmStreamClose(stream, 0); acmDriverClose(driver, 0); - sampleLength = streamHeader.cbDstLengthUsed / sizeof(short); +#endif +#ifdef __APPLE__ + AudioConverterRef converter; + AudioStreamBasicDescription inSourceFormat = {0}; + AudioStreamBasicDescription inDestinationFormat = {0}; + OSStatus status; + + inSourceFormat.mSampleRate = Specimen::SampleRate; + inSourceFormat.mChannelsPerFrame = 1; + inSourceFormat.mFormatID = kAudioFormatMicrosoftGSM; + inSourceFormat.mBytesPerPacket = 0; + + inDestinationFormat.mFormatID = kAudioFormatLinearPCM; + inDestinationFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; + inDestinationFormat.mFramesPerPacket = 1; + inDestinationFormat.mBitsPerChannel = 16; + inDestinationFormat.mSampleRate = inSourceFormat.mSampleRate; + inDestinationFormat.mChannelsPerFrame = inSourceFormat.mChannelsPerFrame; + + status = AudioConverterNew(&inSourceFormat, &inDestinationFormat, &converter); + // TODO: check status. + + char *ptr = compressedData; + UInt32 ioOutputDataPacketSize = GSM_MS_FRAME_SIZE * (compressedSize / GSM_MS_BLOCK_SIZE); + AudioBufferList outOutputData; + outOutputData.mNumberBuffers = 1; + outOutputData.mBuffers[0].mNumberChannels = 1; + outOutputData.mBuffers[0].mDataByteSize = uncompressedSize; + auto uncompressedData = new short[uncompressedSize / 2]; + outOutputData.mBuffers[0].mData = uncompressedData; + + AudioStreamPacketDescription *outPacketDescription = NULL; + status = AudioConverterFillComplexBuffer(converter, + callback, + &ptr, + &ioOutputDataPacketSize, + &outOutputData, + outPacketDescription); + // TODO: check status. + AudioConverterReset(converter); + AudioConverterDispose(converter); + sampleLength = uncompressedSize / 2; +#endif if (sampleData) delete [] sampleData; sampleData = new float[sampleLength]; for (int i = 0; i < sampleLength; i++) sampleData[i] = (float)((double)uncompressedData[i] / 32768.0); @@ -391,6 +442,7 @@ namespace WaveSabreCore samplePlayer.CalcPitch(GetNote() - 60 + Detune + specimen->fineTune * 2.0f - 1.0f + SpecimenVoice::coarseDetune(specimen->coarseTune)); } +#ifdef _WIN32 BOOL __stdcall Specimen::driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport) { if (Specimen::driverId) return 1; @@ -427,4 +479,20 @@ namespace WaveSabreCore } return 1; } +#endif + +#ifdef __APPLE__ + OSStatus Specimen::callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, + AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, + void *inUserData) { + + *ioNumberDataPackets = 1; + ioData->mNumberBuffers = 1; + ioData->mBuffers[0].mNumberChannels = 1; + ioData->mBuffers[0].mDataByteSize = GSM_MS_BLOCK_SIZE; + ioData->mBuffers[0].mData = *((u_int8_t **) inUserData); + (*(char **) inUserData) += GSM_MS_BLOCK_SIZE; + return 0; + } +#endif } diff --git a/WaveSabreCore/src/Thunder.cpp b/WaveSabreCore/src/Thunder.cpp index c40d9094..53673f1c 100644 --- a/WaveSabreCore/src/Thunder.cpp +++ b/WaveSabreCore/src/Thunder.cpp @@ -3,9 +3,17 @@ #include +#ifdef __APPLE__ +#define GSM_FRAME_SIZE 160 +#define GSM_MS_FRAME_SIZE (GSM_FRAME_SIZE * 2) +#define GSM_MS_BLOCK_SIZE 65 +#endif + namespace WaveSabreCore { +#ifdef _WIN32 HACMDRIVERID Thunder::driverId = NULL; +#endif Thunder::Thunder() : SynthDevice(0) @@ -74,6 +82,7 @@ namespace WaveSabreCore compressedData = new char[compressedSize]; memcpy(compressedData, data, compressedSize); +#ifdef _WIN32 acmDriverEnum(driverEnumCallback, NULL, NULL); HACMDRIVER driver = NULL; acmDriverOpen(&driver, driverId, 0); @@ -106,8 +115,50 @@ namespace WaveSabreCore acmStreamClose(stream, 0); acmDriverClose(driver, 0); - sampleLength = streamHeader.cbDstLengthUsed / sizeof(short); +#endif +#ifdef __APPLE__ + AudioConverterRef converter; + AudioStreamBasicDescription inSourceFormat = {0}; + AudioStreamBasicDescription inDestinationFormat = {0}; + OSStatus status; + + inSourceFormat.mSampleRate = Thunder::SampleRate; + inSourceFormat.mChannelsPerFrame = 1; + inSourceFormat.mFormatID = kAudioFormatMicrosoftGSM; + inSourceFormat.mBytesPerPacket = 0; + + inDestinationFormat.mFormatID = kAudioFormatLinearPCM; + inDestinationFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; + inDestinationFormat.mFramesPerPacket = 1; + inDestinationFormat.mBitsPerChannel = 16; + inDestinationFormat.mSampleRate = inSourceFormat.mSampleRate; + inDestinationFormat.mChannelsPerFrame = inSourceFormat.mChannelsPerFrame; + + status = AudioConverterNew(&inSourceFormat, &inDestinationFormat, &converter); + // TODO: check status. + + char *ptr = compressedData; + UInt32 ioOutputDataPacketSize = GSM_MS_FRAME_SIZE * (compressedSize / GSM_MS_BLOCK_SIZE); + AudioBufferList outOutputData; + outOutputData.mNumberBuffers = 1; + outOutputData.mBuffers[0].mNumberChannels = 1; + outOutputData.mBuffers[0].mDataByteSize = uncompressedSize; + auto uncompressedData = new short[uncompressedSize / 2]; + outOutputData.mBuffers[0].mData = uncompressedData; + + AudioStreamPacketDescription *outPacketDescription = NULL; + status = AudioConverterFillComplexBuffer(converter, + callback, + &ptr, + &ioOutputDataPacketSize, + &outOutputData, + outPacketDescription); + // TODO: check status. + AudioConverterReset(converter); + AudioConverterDispose(converter); + sampleLength = uncompressedSize / 2; +#endif if (sampleData) delete [] sampleData; sampleData = new float[sampleLength]; for (int i = 0; i < sampleLength; i++) sampleData[i] = (float)((double)uncompressedData[i] / 32768.0); @@ -147,6 +198,7 @@ namespace WaveSabreCore samplePos = 0; } +#ifdef _WIN32 BOOL __stdcall Thunder::driverEnumCallback(HACMDRIVERID driverId, DWORD_PTR dwInstance, DWORD fdwSupport) { if (Thunder::driverId) return 1; @@ -183,4 +235,20 @@ namespace WaveSabreCore } return 1; } +#endif + +#ifdef __APPLE__ + OSStatus Thunder::callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, + AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, + void *inUserData) { + + *ioNumberDataPackets = 1; + ioData->mNumberBuffers = 1; + ioData->mBuffers[0].mNumberChannels = 1; + ioData->mBuffers[0].mDataByteSize = GSM_MS_BLOCK_SIZE; + ioData->mBuffers[0].mData = *((u_int8_t **) inUserData); + (*(char **) inUserData) += GSM_MS_BLOCK_SIZE; + return 0; + } +#endif } diff --git a/WaveSabreVstLib/CMakeLists.txt b/WaveSabreVstLib/CMakeLists.txt index 330d4d04..c052e9e6 100644 --- a/WaveSabreVstLib/CMakeLists.txt +++ b/WaveSabreVstLib/CMakeLists.txt @@ -1,3 +1,9 @@ +if(APPLE) + set(EXTRA_VSTGUI_COCOA + ${VSTSDK3_DIR}/vstgui.sf/vstgui/cocoasupport.mm + ${VSTSDK3_DIR}/vstgui.sf/vstgui/cvstguitimer.cpp) +endif(APPLE) + add_library(WaveSabreVstLib STATIC ${VSTSDK3_DIR}/public.sdk/source/vst2.x/audioeffect.cpp ${VSTSDK3_DIR}/public.sdk/source/vst2.x/audioeffectx.cpp @@ -24,6 +30,7 @@ add_library(WaveSabreVstLib STATIC ${VSTSDK3_DIR}/vstgui.sf/vstgui/vstcontrols.cpp ${VSTSDK3_DIR}/vstgui.sf/vstgui/vstgui.cpp ${VSTSDK3_DIR}/vstgui.sf/vstgui/vstguidebug.cpp + ${EXTRA_VSTGUI_COCOA} ${VSTSDK3_DIR}/vstgui.sf/zlib/adler32.c ${VSTSDK3_DIR}/vstgui.sf/zlib/compress.c ${VSTSDK3_DIR}/vstgui.sf/zlib/crc32.c diff --git a/WaveSabreVstLib/src/ImageManager.cpp b/WaveSabreVstLib/src/ImageManager.cpp index 5fa1f9c7..c174c24b 100644 --- a/WaveSabreVstLib/src/ImageManager.cpp +++ b/WaveSabreVstLib/src/ImageManager.cpp @@ -1,7 +1,13 @@ #include #include +#ifdef _WIN32 #include "../../Data/resource.h" +#endif + +#ifdef __APPLE__ +#include "../../Data/resourcestr.h" +#endif using namespace std; From 48e7c7c74a2de89b024ee42ae846773b313ce150 Mon Sep 17 00:00:00 2001 From: fefal64 Date: Thu, 8 Jul 2021 22:06:05 +0100 Subject: [PATCH 02/13] Fix CNewFileSelector usage on Windows but requires editing vstgui.h. Redefinition of _WIN32_WINNT to 0x0600 is required is vstgui.h (line 69). --- WaveSabreVstLib/CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/WaveSabreVstLib/CMakeLists.txt b/WaveSabreVstLib/CMakeLists.txt index c052e9e6..26c88ace 100644 --- a/WaveSabreVstLib/CMakeLists.txt +++ b/WaveSabreVstLib/CMakeLists.txt @@ -1,8 +1,12 @@ if(APPLE) - set(EXTRA_VSTGUI_COCOA + set(EXTRA_VSTGUI ${VSTSDK3_DIR}/vstgui.sf/vstgui/cocoasupport.mm ${VSTSDK3_DIR}/vstgui.sf/vstgui/cvstguitimer.cpp) endif(APPLE) +if(MSVC) + set(EXTRA_VSTGUI + ${VSTSDK3_DIR}/vstgui.sf/vstgui/winfileselector.cpp) +endif(MSVC) add_library(WaveSabreVstLib STATIC ${VSTSDK3_DIR}/public.sdk/source/vst2.x/audioeffect.cpp @@ -30,7 +34,7 @@ add_library(WaveSabreVstLib STATIC ${VSTSDK3_DIR}/vstgui.sf/vstgui/vstcontrols.cpp ${VSTSDK3_DIR}/vstgui.sf/vstgui/vstgui.cpp ${VSTSDK3_DIR}/vstgui.sf/vstgui/vstguidebug.cpp - ${EXTRA_VSTGUI_COCOA} + ${EXTRA_VSTGUI} ${VSTSDK3_DIR}/vstgui.sf/zlib/adler32.c ${VSTSDK3_DIR}/vstgui.sf/zlib/compress.c ${VSTSDK3_DIR}/vstgui.sf/zlib/crc32.c @@ -61,7 +65,7 @@ target_include_directories(WaveSabreVstLib PUBLIC target_compile_definitions(WaveSabreVstLib PUBLIC USE_LIBPNG) if(MSVC) - target_compile_definitions(WaveSabreVstLib PUBLIC _CRT_SECURE_NO_WARNINGS) + target_compile_definitions(WaveSabreVstLib PUBLIC _CRT_SECURE_NO_WARNINGS VSTGUI_NEW_CFILESELECTOR) target_compile_options(WaveSabreVstLib PUBLIC /EHsc) set_source_files_properties(${VSTSDK3_DIR}/vstgui.sf/vstgui/vstgui.cpp ${VSTSDK3_DIR}/vstgui.sf/zlib/minigzip.c From 0c06a492620ff26e3a88bafd2a753dba4511a85e Mon Sep 17 00:00:00 2001 From: fefal64 Date: Fri, 9 Jul 2021 18:58:56 +0100 Subject: [PATCH 03/13] Fix: editing vstgui.h is not required anymore. Surprisingly /D compiler option takes precedence over #define and windows vista features are found. --- WaveSabreVstLib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WaveSabreVstLib/CMakeLists.txt b/WaveSabreVstLib/CMakeLists.txt index 26c88ace..05eacb7c 100644 --- a/WaveSabreVstLib/CMakeLists.txt +++ b/WaveSabreVstLib/CMakeLists.txt @@ -65,7 +65,7 @@ target_include_directories(WaveSabreVstLib PUBLIC target_compile_definitions(WaveSabreVstLib PUBLIC USE_LIBPNG) if(MSVC) - target_compile_definitions(WaveSabreVstLib PUBLIC _CRT_SECURE_NO_WARNINGS VSTGUI_NEW_CFILESELECTOR) + target_compile_definitions(WaveSabreVstLib PUBLIC _CRT_SECURE_NO_WARNINGS VSTGUI_NEW_CFILESELECTOR _WIN32_WINNT=0x0600) target_compile_options(WaveSabreVstLib PUBLIC /EHsc) set_source_files_properties(${VSTSDK3_DIR}/vstgui.sf/vstgui/vstgui.cpp ${VSTSDK3_DIR}/vstgui.sf/zlib/minigzip.c From 42e6e8c2fa092921ae28b40f335ef8389382461a Mon Sep 17 00:00:00 2001 From: Fefa Date: Fri, 9 Jul 2021 20:45:50 +0100 Subject: [PATCH 04/13] The fix was fake. vstgui patch included. The /D switch worked because I was compiling with a vstgui.h already patched. So no surprise. Because I can not see any workaround but patching vstgui.cpp and vstgui.h, a patch is included and AppVeyor script is modified to apply the patch. --- .appveyor.yml | 1 + Data/vstgui.patch | 26 ++++++++++++++++++++++++++ WaveSabreVstLib/CMakeLists.txt | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Data/vstgui.patch diff --git a/.appveyor.yml b/.appveyor.yml index 8a6de92f..d5820610 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,6 +14,7 @@ install: Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" Expand-Archive "vstsdk.zip" "C:\tmp" } + - git apply -p2 --directory ..\..\tmp --stat Data\vstgui.patch build_script: - mkdir build diff --git a/Data/vstgui.patch b/Data/vstgui.patch new file mode 100644 index 00000000..12c1a19a --- /dev/null +++ b/Data/vstgui.patch @@ -0,0 +1,26 @@ +diff --git a/vstsdk.orig/VST3 SDK/vstgui.sf/vstgui/vstgui.cpp b/vstsdk/VST3 SDK/vstgui.sf/vstgui/vstgui.cpp +index dd081cf..29f0467 100644 +--- a/vstsdk.orig/VST3 SDK/vstgui.sf/vstgui/vstgui.cpp ++++ b/vstsdk/VST3 SDK/vstgui.sf/vstgui/vstgui.cpp +@@ -217,7 +217,7 @@ END_NAMESPACE_VSTGUI + //----------------------------------------------------------------------------- + #if MAC + //----------------------------------------------------------------------------- +-#include ++#include + #include + + #if MAC_CARBON +diff --git a/vstsdk.orig/VST3 SDK/vstgui.sf/vstgui/vstgui.h b/vstsdk/VST3 SDK/vstgui.sf/vstgui/vstgui.h +index ad75218..86db083 100644 +--- a/vstsdk.orig/VST3 SDK/vstgui.sf/vstgui/vstgui.h ++++ b/vstsdk/VST3 SDK/vstgui.sf/vstgui/vstgui.h +@@ -66,7 +66,7 @@ + #endif + + #if WINDOWS +- #define _WIN32_WINNT 0x0501 ++ #define _WIN32_WINNT 0x0600 + #ifndef GDIPLUS + #define GDIPLUS 1 // by default we use GDIPlus + #endif diff --git a/WaveSabreVstLib/CMakeLists.txt b/WaveSabreVstLib/CMakeLists.txt index 05eacb7c..26c88ace 100644 --- a/WaveSabreVstLib/CMakeLists.txt +++ b/WaveSabreVstLib/CMakeLists.txt @@ -65,7 +65,7 @@ target_include_directories(WaveSabreVstLib PUBLIC target_compile_definitions(WaveSabreVstLib PUBLIC USE_LIBPNG) if(MSVC) - target_compile_definitions(WaveSabreVstLib PUBLIC _CRT_SECURE_NO_WARNINGS VSTGUI_NEW_CFILESELECTOR _WIN32_WINNT=0x0600) + target_compile_definitions(WaveSabreVstLib PUBLIC _CRT_SECURE_NO_WARNINGS VSTGUI_NEW_CFILESELECTOR) target_compile_options(WaveSabreVstLib PUBLIC /EHsc) set_source_files_properties(${VSTSDK3_DIR}/vstgui.sf/vstgui/vstgui.cpp ${VSTSDK3_DIR}/vstgui.sf/zlib/minigzip.c From 664f350f2be849b4d9dea6c2fce6b008c53b6f96 Mon Sep 17 00:00:00 2001 From: Fefa Date: Fri, 9 Jul 2021 20:56:18 +0100 Subject: [PATCH 05/13] Remove --stat so the patch is applied (OMG). --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index d5820610..e9777c6f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,7 +14,7 @@ install: Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" Expand-Archive "vstsdk.zip" "C:\tmp" } - - git apply -p2 --directory ..\..\tmp --stat Data\vstgui.patch + - git apply -p2 --directory ..\..\tmp Data\vstgui.patch build_script: - mkdir build From 14da3819a0e2110957e12ba159119b99738bbfdf Mon Sep 17 00:00:00 2001 From: Fefa Date: Fri, 9 Jul 2021 21:03:37 +0100 Subject: [PATCH 06/13] Trying to fix path for apply patch. --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index e9777c6f..55de5ded 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,7 +14,7 @@ install: Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" Expand-Archive "vstsdk.zip" "C:\tmp" } - - git apply -p2 --directory ..\..\tmp Data\vstgui.patch + - git apply -p2 --directory ../../tmp Data\vstgui.patch build_script: - mkdir build From 808a7141df0122ab644a9e5847077c093aec605d Mon Sep 17 00:00:00 2001 From: Fefa Date: Fri, 9 Jul 2021 21:09:57 +0100 Subject: [PATCH 07/13] Last chance to apply the patch. --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 55de5ded..29395175 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,7 +14,7 @@ install: Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" Expand-Archive "vstsdk.zip" "C:\tmp" } - - git apply -p2 --directory ../../tmp Data\vstgui.patch + - git apply -p2 --unsafe-paths --directory /tmp Data\vstgui.patch build_script: - mkdir build From 5fee710aa3c886ed70ab04614a3dbda314523b6d Mon Sep 17 00:00:00 2001 From: Fefa Date: Sun, 11 Jul 2021 00:25:56 +0100 Subject: [PATCH 08/13] First try to add macOS platform in AppVeyor CI. --- .appveyor.yml | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 29395175..2de2f062 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,18 +1,21 @@ version: '{build}' -image: Visual Studio 2013 -platform: - - Win32 - - x64 +environment: + matrix: + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + platform: Win32 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + platform: x64 + - APPVEYOR_BUILD_WORKER_IMAGE: macOS cache: - - C:\tmp\VST3 SDK + - \tmp\VST3 SDK install: - ps: | - if (-Not (Test-Path "C:\tmp\VST3 SDK")) { + if (-Not (Test-Path "\tmp\VST3 SDK")) { Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" - Expand-Archive "vstsdk.zip" "C:\tmp" + Expand-Archive "vstsdk.zip" "\tmp" } - git apply -p2 --unsafe-paths --directory /tmp Data\vstgui.patch @@ -23,3 +26,13 @@ build_script: - msbuild /v:minimal /nologo WaveSabre.sln - msbuild /v:minimal /nologo /property:Configuration="MinSizeRel" WaveSabre.sln - cd .. + +for: + - + matrix: + only: + - image: macOS + build_script: + - cmake -B build -G Xcode + - xcodebuild -project build/WaveSabre.xcodeproj -scheme ALL_BUILD -configuration Release build + From ce64fd1669286f7dd93367471fcfe02c66ec888b Mon Sep 17 00:00:00 2001 From: Fefa Date: Sun, 11 Jul 2021 00:59:19 +0100 Subject: [PATCH 09/13] For CI, added libgsm installation on macOS and patching on cache failure. --- .appveyor.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2de2f062..a1eeaf33 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,23 +1,28 @@ version: '{build}' -environment: - matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 +image: + - Visual Studio 2013 + - macOS + +platform: + - Win32 + - x64 + +matrix: + exclude: + - image: macOS platform: Win32 - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 - platform: x64 - - APPVEYOR_BUILD_WORKER_IMAGE: macOS cache: - - \tmp\VST3 SDK + - \tmp\VST3 SDK -> Data/vstgui.patch install: - ps: | if (-Not (Test-Path "\tmp\VST3 SDK")) { Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" Expand-Archive "vstsdk.zip" "\tmp" + & git apply -p2 --unsafe-paths --directory /tmp Data/vstgui.patch } - - git apply -p2 --unsafe-paths --directory /tmp Data\vstgui.patch build_script: - mkdir build @@ -33,6 +38,7 @@ for: only: - image: macOS build_script: + - brew install libgsm - cmake -B build -G Xcode - xcodebuild -project build/WaveSabre.xcodeproj -scheme ALL_BUILD -configuration Release build From a5404e91c75167a1e3c28bcea79891184c57e450 Mon Sep 17 00:00:00 2001 From: Fefa Date: Sun, 11 Jul 2021 01:17:20 +0100 Subject: [PATCH 10/13] For CI, git patch disallow symbolic links in macOS. --- .appveyor.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a1eeaf33..2923f0e2 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -14,13 +14,13 @@ matrix: platform: Win32 cache: - - \tmp\VST3 SDK -> Data/vstgui.patch + - c:\tmp\VST3 SDK -> Data/vstgui.patch install: - ps: | - if (-Not (Test-Path "\tmp\VST3 SDK")) { + if (-Not (Test-Path "c:\tmp\VST3 SDK")) { Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" - Expand-Archive "vstsdk.zip" "\tmp" + Expand-Archive "vstsdk.zip" "c:\tmp" & git apply -p2 --unsafe-paths --directory /tmp Data/vstgui.patch } @@ -37,8 +37,16 @@ for: matrix: only: - image: macOS - build_script: + cache: /private/tmp/VST3 SDK -> Data/vstgui.patch + install: + - ps: | + if (-Not (Test-Path "/private/tmp/VST3 SDK")) { + Invoke-WebRequest "https://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip" -OutFile "vstsdk.zip" + Expand-Archive "vstsdk.zip" "/private/tmp" + & git apply -p2 --unsafe-paths --directory /private/tmp Data/vstgui.patch + } - brew install libgsm - - cmake -B build -G Xcode + build_script: + - cmake -B build -G Xcode -DVSTSDK3_DIR="/private/tmp/VST3 SDK" - xcodebuild -project build/WaveSabre.xcodeproj -scheme ALL_BUILD -configuration Release build From ba9717c8fe9174ba8e271ccc8dfd05c4a004a513 Mon Sep 17 00:00:00 2001 From: Fefa Date: Sun, 11 Jul 2021 12:25:47 +0100 Subject: [PATCH 11/13] For CI, avoid brew update. --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2923f0e2..3a2eb594 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -45,7 +45,7 @@ for: Expand-Archive "vstsdk.zip" "/private/tmp" & git apply -p2 --unsafe-paths --directory /private/tmp Data/vstgui.patch } - - brew install libgsm + - HOMEBREW_NO_AUTO_UPDATE=1 brew install libgsm build_script: - cmake -B build -G Xcode -DVSTSDK3_DIR="/private/tmp/VST3 SDK" - xcodebuild -project build/WaveSabre.xcodeproj -scheme ALL_BUILD -configuration Release build From d9f159205e337e199a995d2b7dc95ea5175ff6a7 Mon Sep 17 00:00:00 2001 From: Fefa Date: Sun, 11 Jul 2021 13:01:37 +0100 Subject: [PATCH 12/13] For CI, do not cleanup after brew install and try to get success for cache save. VSTSDK download is failing by some reason just for the Visual Studio 2013 + x64 job. and it makes an unsuccessful build, so cache is not created. Let's try to get success by removing that job and put in it again in next commit. --- .appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 3a2eb594..17c71ffe 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,6 +12,8 @@ matrix: exclude: - image: macOS platform: Win32 + - image: Visual Studio 2013 + platform: x64 cache: - c:\tmp\VST3 SDK -> Data/vstgui.patch @@ -45,7 +47,7 @@ for: Expand-Archive "vstsdk.zip" "/private/tmp" & git apply -p2 --unsafe-paths --directory /private/tmp Data/vstgui.patch } - - HOMEBREW_NO_AUTO_UPDATE=1 brew install libgsm + - HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1 brew install libgsm build_script: - cmake -B build -G Xcode -DVSTSDK3_DIR="/private/tmp/VST3 SDK" - xcodebuild -project build/WaveSabre.xcodeproj -scheme ALL_BUILD -configuration Release build From 019b91944511ca57f463e177e28468c698932282 Mon Sep 17 00:00:00 2001 From: Fefa Date: Sun, 11 Jul 2021 13:13:32 +0100 Subject: [PATCH 13/13] For CI, Restore Visual Studio 2013 + x64, and let's check cache usage. --- .appveyor.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 17c71ffe..56f79cc0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -12,8 +12,6 @@ matrix: exclude: - image: macOS platform: Win32 - - image: Visual Studio 2013 - platform: x64 cache: - c:\tmp\VST3 SDK -> Data/vstgui.patch