Skip to content

Commit

Permalink
padreEnvelopeProcessor: fixes/tweaks
Browse files Browse the repository at this point in the history
take LFO generator:
- allow for generating more envelope points (use envUtil::GetEnvelopeStateChunkBig() instead of PadreGetEnvelopeState())
#1158 (partly)

padreUtils:
- remove GetEnvelopeState()

+add files: envelope.hpp/.cpp (place for general envelope utility functions), #include in stdafx.h, update CMakeLists.txt

+Snapshots:
- TrackSends: use envUtil::GetEnvelopeStateChunkBig() (instead of GetEnvelopeStateChunk())
  • Loading branch information
nofishonfriday committed Oct 4, 2019
1 parent 629a566 commit 1460bdf
Show file tree
Hide file tree
Showing 10 changed files with 195 additions and 49 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ add_library(sws SHARED
sws_waitdlg.cpp
sws_wnd.cpp
Utility/Base64.cpp
Utility/envelope.cpp
Zoom.cpp
)

Expand Down
66 changes: 53 additions & 13 deletions ObjectState/TrackSends.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,30 +270,47 @@ void TrackSends::Build(MediaTrack* tr)
if (strncmp(line, searchStr, strlen(searchStr)) == 0) {

// get the AUXVOL, AUXPAN, AUXMUTE subchunks
// note: chunks don't work properly with AIs currently
// note: envelope points in automations items aren't included in envelope chunks
// https://forum.cockos.com/showthread.php?t=205279
char AUXVOLchunk[4096]; char AUXPANchunk[4096]; char AUXMUTEchunk[4096];
WDL_FastString AUXVOLstr, AUXPANstr, AUXMUTEstr;
std::string AUXVOLstr, AUXPANstr, AUXMUTEstr;

TrackEnvelope* auxrcvVolEnv = (TrackEnvelope*)GetSetTrackSendInfo(pDest, -1, receiveIdx, "P_ENV", (void*)"<VOLENV");
TrackEnvelope* auxrcvPanEnv = (TrackEnvelope*)GetSetTrackSendInfo(pDest, -1, receiveIdx, "P_ENV", (void*)"<PANENV");
TrackEnvelope* auxrcvMuteEnv = (TrackEnvelope*)GetSetTrackSendInfo(pDest, -1, receiveIdx, "P_ENV", (void*)"<MUTEENV");

if (auxrcvVolEnv) {
GetEnvelopeStateChunk(auxrcvVolEnv, AUXVOLchunk, sizeof(AUXVOLchunk), true);
AUXVOLstr.Set(AUXVOLchunk);
if (auxrcvVolEnv)
{
try {
AUXVOLstr = envUtil::GetEnvelopeStateChunkBig(auxrcvVolEnv);
}
catch (const envUtil::bad_get_env_chunk_big &ex) {

DisplayStoreSendEnvError(tr, AUXVOL, ex.what());
}
}

if (auxrcvPanEnv) {
GetEnvelopeStateChunk(auxrcvPanEnv, AUXPANchunk, sizeof(AUXPANchunk), true);
AUXPANstr.Set(AUXPANchunk);
if (auxrcvPanEnv)
{
try {
AUXPANstr = envUtil::GetEnvelopeStateChunkBig(auxrcvPanEnv);
}
catch (const envUtil::bad_get_env_chunk_big& ex) {
DisplayStoreSendEnvError(tr, AUXPAN, ex.what());
}

}

if (auxrcvMuteEnv) {
GetEnvelopeStateChunk(auxrcvMuteEnv, AUXMUTEchunk, sizeof(AUXMUTEchunk), true);
AUXMUTEstr.Set(AUXMUTEchunk);
if (auxrcvMuteEnv)
{
try {
AUXMUTEstr = envUtil::GetEnvelopeStateChunkBig(auxrcvMuteEnv);
}
catch (const envUtil::bad_get_env_chunk_big& ex) {
DisplayStoreSendEnvError(tr, AUXMUTE, ex.what());
}

}
m_sends.Add(new TrackSend(&guid, line, AUXVOLstr.Get(), AUXPANstr.Get(), AUXMUTEstr.Get()));
m_sends.Add(new TrackSend(&guid, line, AUXVOLstr.c_str(), AUXPANstr.c_str(), AUXMUTEstr.c_str()));
}
}
SWS_FreeHeapPtr(trackStr);
Expand Down Expand Up @@ -432,3 +449,26 @@ void TrackSends::GetChunk(WDL_FastString* chunk)
for (int i = 0; i < m_sends.GetSize(); i++)
m_sends.Get(i)->GetChunk(chunk);
}

void TrackSends::DisplayStoreSendEnvError(MediaTrack* tr, EnvTypes envType, std::string exception)
{
std::ostringstream ss;
ss << "Track " << static_cast<int>(GetMediaTrackInfo_Value(tr, "IP_TRACKNUMBER")) << ":\n";

switch (envType)
{
case AUXVOL:
ss << __LOCALIZE("Error storing send volume envelope!\n", "sws_mbox");
break;
case AUXPAN:
ss << __LOCALIZE("Error storing send pan envelope!\n", "sws_mbox");
break;
case AUXMUTE:
ss << __LOCALIZE("Error storing send mute envelope!\n", "sws_mbox");
break;
}
// ss << __LOCALIZE(exception.c_str(), "sws_mbox");
ss << __localizeFunc(exception.c_str(), "sws_mbox", 0);

MessageBox(g_hwndParent, ss.str().c_str(), __LOCALIZE("SWS Snapshots - Error", "sws_mbox"), MB_OK);
}
10 changes: 9 additions & 1 deletion ObjectState/TrackSends.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,16 @@ class TrackSends
void Build(MediaTrack* tr);
void UpdateReaper(MediaTrack* tr, WDL_PtrList<TrackSendFix>* pFix);
void GetChunk(WDL_FastString* chunk);

// TODO these should be private
WDL_PtrList<WDL_FastString> m_hwSends;
WDL_PtrList<TrackSend> m_sends;

private:
enum EnvTypes {
AUXVOL = 0,
AUXPAN,
AUXMUTE
};
void DisplayStoreSendEnvError(MediaTrack* tr, EnvTypes envName, std::string exception);
};
16 changes: 11 additions & 5 deletions Padre/padreEnvelopeProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -713,9 +713,16 @@ EnvelopeProcessor::ErrorCode EnvelopeProcessor::generateTakeLfo(MediaItem_Take*
// return eERRORCODE_NULLTIMESELECTION;

string newState;
char* envState = PadresGetEnvelopeState(envelope);
if(!envState)
string envStateStr;
try {
envStateStr = envUtil::GetEnvelopeStateChunkBig(envelope);
}
catch (envUtil::bad_get_env_chunk_big) {

return eERRORCODE_NOOBJSTATE;
}

char* envState = &envStateStr[0];
double dTmp[2];
int iTmp;
char* token = strtok(envState, "\n");
Expand Down Expand Up @@ -790,7 +797,6 @@ EnvelopeProcessor::ErrorCode EnvelopeProcessor::generateTakeLfo(MediaItem_Take*
writeLfoPoints(newState, dStartPos, dEndPos, dValMin, dValMax, dFreq, dStrength, dOffset, dDelay, tWaveShape, dPrecision);
newState.append(">\n");
*/
free(envState);
if(!newState.size() || !GetSetEnvelopeState(envelope, (char*)newState.c_str(), (int)newState.size()))
return eERRORCODE_UNKNOWN;

Expand Down Expand Up @@ -1085,10 +1091,10 @@ EnvelopeProcessor::ErrorCode EnvelopeProcessor::processTakeEnv(MediaItem_Take* t
if(!envelope)
return eERRORCODE_NOENVELOPE;

char* envState = PadresGetEnvelopeState(envelope);
string envStateStr = envUtil::GetEnvelopeStateChunkBig(envelope);
char* envState = &envStateStr[0];
string newState;
ErrorCode res = processPoints(envState, newState, dStartPos, dEndPos, dValMin, dValMax, envModType, dStrength, dOffset);
free(envState);

if(!newState.size() || !GetSetEnvelopeState(envelope, (char*)newState.c_str(), (int)newState.size()))
res = eERRORCODE_UNKNOWN;
Expand Down
28 changes: 0 additions & 28 deletions Padre/padreUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,34 +230,6 @@ double EnvSignalProcessorFade(double dPos, double dLength, double dStrength, boo
return pow(((dLength - dPos)/dLength), dStrength);
}

char* PadresGetEnvelopeState(TrackEnvelope* envelope)
{
//! \note GetSetObjectState() does not work for take envelopes
// While loop shamelessly stolen from SWS! :)
if(!envelope)
return NULL;

char* envState = NULL;
int iEnvStateMaxSize = 65536;
int iEnvStateSize = 256;
while(true)
{
envState = (char*)realloc(envState, iEnvStateSize);
envState[0] = 0;
bool bRes = GetSetEnvelopeState(envelope, envState, iEnvStateSize);
if(bRes && (strlen(envState)!=iEnvStateSize-1))
break;
if (!bRes || (iEnvStateSize>=iEnvStateMaxSize))
{
free(envState);
return NULL;
}
iEnvStateSize *= 2;
}
return envState;

}

void ShowConsoleMsgEx(const char* format, ...)
{
va_list args;
Expand Down
2 changes: 0 additions & 2 deletions Padre/padreUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ double WaveformGeneratorRandom(double t, double dFreq, double dDelay);

double EnvSignalProcessorFade(double dPos, double dLength, double dStrength, bool bFadeIn);

char* PadresGetEnvelopeState(TrackEnvelope* envelope);

void ShowConsoleMsgEx(const char* format, ...);

void GetTimeSegmentPositions(TimeSegment timeSegment, double &dStartPos, double &dEndPos, MediaItem* item = NULL);
Expand Down
70 changes: 70 additions & 0 deletions Utility/envelope.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/******************************************************************************
/ envelope.cpp
/
/ Copyright (c) 2019
/
/ Permission is hereby granted, free of charge, to any person obtaining a copy
/ of this software and associated documentation files (the "Software"), to deal
/ in the Software without restriction, including without limitation the rights to
/ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
/ of the Software, and to permit persons to whom the Software is furnished to
/ do so, subject to the following conditions:
/
/ The above copyright notice and this permission notice shall be included in all
/ copies or substantial portions of the Software.
/
/ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
/ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
/ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
/ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
/ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
/ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
/ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
/ OTHER DEALINGS IN THE SOFTWARE.
/
******************************************************************************/

#include "stdafx.h"
#include "envelope.hpp"

namespace envUtil
{
// wraps GetEnvelopeStateChunk() to make it more save
// until maybe it gets enhanced one day
// https://forum.cockos.com/showthread.php?p=2142245#post2142245
// throws envUtil::bad_get_env_chunk_big on failure
std::string GetEnvelopeStateChunkBig(TrackEnvelope* envelope, bool isUndo /*= false*/)
{
std::string buffer(1024, '\0');

while (true) {
// can't use std::string::front (C++11) as we're targeting OSX 10.5 (as of September 2019)
// though &operator[0] should be ok:
// https://github.com/reaper-oss/sws/pull/1202#issuecomment-532476783
// if (!GetEnvelopeStateChunk(envelope, &buffer.front(), buffer.size() + 1, isUndo))
if (!GetEnvelopeStateChunk(envelope, &buffer[0], buffer.size() + 1, isUndo))
break;

const size_t endpos = buffer.find('\0');

if (endpos != std::string::npos) {
buffer.resize(endpos);
return buffer;
}

if (buffer.size() > 100 << 20) { // 100 MiB
throw envUtil::bad_get_env_chunk_big("The envelope chunk size exceeded the 100 MiB limit");
break;
}

try {
buffer.resize(buffer.size() * 2);
}
catch (const std::bad_alloc) {
throw envUtil::bad_get_env_chunk_big("std::bad_alloc thrown");
}
}

return {};
}
}
39 changes: 39 additions & 0 deletions Utility/envelope.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/******************************************************************************
/ envelope.hpp
/
/ Copyright (c) 2019
/
/ Permission is hereby granted, free of charge, to any person obtaining a copy
/ of this software and associated documentation files (the "Software"), to deal
/ in the Software without restriction, including without limitation the rights to
/ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
/ of the Software, and to permit persons to whom the Software is furnished to
/ do so, subject to the following conditions:
/
/ The above copyright notice and this permission notice shall be included in all
/ copies or substantial portions of the Software.
/
/ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
/ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
/ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
/ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
/ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
/ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
/ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
/ OTHER DEALINGS IN THE SOFTWARE.
/
******************************************************************************/

#pragma once

namespace envUtil
{
std::string GetEnvelopeStateChunkBig(TrackEnvelope* envelope, bool isUndo = false);

class bad_get_env_chunk_big : public std::runtime_error {
public:
using runtime_error::runtime_error;
};
}


1 change: 1 addition & 0 deletions stdafx.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
#include "Padre/padreMidi.h"
#include "Padre/padreMidiItemProcBase.h"
#include "Breeder/BR_Timer.h"
#include "Utility/envelope.hpp"

#ifdef _WIN32
# include "Utility/win32-utf8.h"
Expand Down
11 changes: 11 additions & 0 deletions whatsnew.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
- Fix the install path being initially empty when launching the Windows installer if REAPER is not installed
- Fix nonworking check for running REAPER processes

Fixes:
PADRE Envelope LFO generator: (Issue #1158)
- allow for generating more points
- account for take playrate

Snapshots:
- harden getting send envelopes (displays error message in case of failure)
Reminder from SWS v2.10.0 change log:
Send envelops should now be stored/recalled correctly with Snapshots (long standing bug), thogh it hasn't been tested much
Since snapshots are based on state chunks, changes within AI envelopes are not stored/recalled currently (https://forum.cockos.com/showthread.php?t=205406|FR|), though AI properties (e.g. position) should be recalled correctly. Also note that when deleting an AI and trying to recall a previously stored snapshot which contains this AI it won't be recalled correctly.

!v2.10.0 #1 Featured build (February 6, 2019)
Mega thanks to nofish and cfillion for their many contributions, and X-Raym for doing the tedious work of merging everything into a release.
Recommended use of REAPER 5.965.
Expand Down

0 comments on commit 1460bdf

Please sign in to comment.