📄 mixo_mi.cpp
字号:
#include <stdio.h>
#include <string>
#include <sstream>
#include <process.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <afxext.h>
#include <Afxdisp.h>
#include <afxwin.h>
#include <afxcmn.h>
#include <mmsystem.h>
#include "resource.h"
#include "MixerStatus.h"
#include "MixDlg.h"
#include "dsplib.h"
#include "version.h"
//#include "../MachineInterface.h"
#include "mdk.h"
//#include "resource.h"
//#include "configdlg.h"
using namespace std;
#define BYTES_PER_SAMPLE 4 // 2 * 16bits
#define ADF_STEREO 1 // this is currently required by buzz
/*
class CApp : public CWinApp
{
public:
virtual BOOL InitInstance()
{
AfxEnableControlContainer();
return TRUE;
}
};
CApp App;
const CWinApp &g_GetApplication()
{
return App;
}
*/
CMachineParameter const cpaPreset =
{
pt_word, // type
"Preset",
"Preset Number", // description
1, // MinValue
0xffff, // MaxValue
0, // NoValue
0 // Flags
};
CMachineParameter const cpaMode =
{
pt_byte, // type
"Mode",
"Mode: 0=Normal 1=Mute 2=Bypass", // description
0, // MinValue
0x2, // MaxValue
0xff, // NoValue
};
CMachineParameter const *pParameters[] =
{
&cpaPreset,
&cpaMode,
NULL
};
CMachineAttribute const *pAttributes[] =
{
NULL,
};
#pragma pack(1)
class gvals
{
public:
word wdPreset;
byte btMode;
};
class avals
{
public:
int symmetric;
};
#pragma pack()
CMachineInfo const MacInfo =
{
MT_EFFECT, // type
MI_VERSION,
MIF_DOES_INPUT_MIXING|MIF_MONO_TO_STEREO, // flags
0, // min tracks
0, // max tracks
2, // numGlobalParameters
0, // numTrackParameters
pParameters,
0,
pAttributes,
#ifdef _DEBUG
"mimo's miXo (Debug build)", // name
#else
"mimo's miXo", // name
#endif
"miXo", // short name
"mimo", // author
"Open Mixer..\nAbout..",
NULL
};
//Definitions for Costum Local Contexthandlers
typedef const enum {
celc_OpenMixer=0,
celc_About
}CELocalCommands;
class mi;
class miex : public CMDKMachineInterfaceEx
{
mi *m_pcMI;
public:
friend class mi;
miex();
virtual ~miex();
void SetInterface(mi *m) {m_pcMI=m;}
virtual void AddInput(char const *macname, bool stereo); // called when input is added to a machine
virtual void DeleteInput(char const *macename);
virtual void RenameInput(char const *macoldname, char const *macnewname);
virtual void Input(float *psamples, int numsamples, float amp);
virtual void SetInputChannels(char const *macname, bool stereo);
virtual bool HandleInput(int index, int amp, int pan);
};
class mi : public CMachineInterface//CMDKMachineInterface
{
public:
mi();
virtual ~mi();
virtual void Tick();
virtual void Stop();
virtual void Command(int const i);
virtual char const *DescribeValue(int const param, int const value);
private:
miex ex;
// float m_fAmp;
CMixerStatus m_cMixerStatus;
void AboutBox();
void OpenMixer();
void Initialize();
CMixDlg *m_pcMixDlg;
string m_strMachineName;
private:
gvals gval;
avals aval;
gvals m_StoredGvals;
protected:
static const char m_cszModuleName[];
public:
bool DblClkHandler(void *);
void Error(char const *msg);
// virtual CMDKMachineInterfaceEx *GetEx() {return &ex;};
virtual void OutputModeChanged(bool stereo) {}
virtual bool Work(float *psamples, int numsamples, int const mode){ return false; };
virtual bool WorkStereo(float *psamples, int numsamples, int const mode){ return false; };
virtual bool WorkMonoToStereo(float *pin, float *pout, int numsamples, int const mode);
virtual void Init(CMachineDataInput * const pi);
virtual void Save(CMachineDataOutput * const po);
CMixDlg *GetMixer() { return m_pcMixDlg; }
//from waveout.h
};
DLL_EXPORTS
const char mi::m_cszModuleName[]="mimo's miXo";
mi::mi() : CMachineInterface(),m_cMixerStatus(),m_pcMixDlg(NULL),
m_strMachineName()
{
GlobalVals = &gval;
}
mi::~mi()
{
if(m_pcMixDlg)
delete m_pcMixDlg;
}
void mi::Init(CMachineDataInput * const pi)
{
pCB->SetMachineInterfaceEx(&ex);
CMachine *pcThisMachine=pCB->GetThisMachine();
pCB->SetnumOutputChannels(pcThisMachine,2);
m_strMachineName=pCB->GetMachineName(pcThisMachine);
pCB->SetEventHandler(pcThisMachine,DoubleClickMachine,(EVENT_HANDLER_PTR)DblClkHandler,(void*)this);
// SetOutputMode( true ); // If true, the MDKWork will never be called, meaning that Buzz will convert a mono signal to
// stereo itself and call MDKWorkStereo insted.
// If false, MDKWork will be called in mono cases, and the output should be mono
ex.SetInterface(this);
m_cMixerStatus.SetCallbacks(pCB);
if(!m_pcMixDlg) {
try{
m_pcMixDlg=new CMixDlg(m_strMachineName.c_str(),&m_cMixerStatus,m_cszModuleName);
}catch(CAbException &e){
Error(e.GetMessage().c_str());
}
}
if(pi)
m_cMixerStatus.Init(pi);
}
void mi::Save(CMachineDataOutput * const po)
{
if(po)
m_cMixerStatus.Save(po);
}
bool mi::WorkMonoToStereo(float *pin, float *pout, int numsamples, int const mode)
{
// char sz[]={'0'+mode,' ','0'+numsamples};
// OutputDebugString(sz);
bool bRet=true;
#ifdef _DEBUG
try{
#endif
if(mode != WM_READ) {
if((bRet=m_cMixerStatus.IsUpdateFlagSet()))
m_cMixerStatus.CopyBufNClear(pout,numsamples);
}else
bRet=false;
m_pcMixDlg->DoPendingKeyEvents();
m_pcMixDlg->UpdateTracks();
#ifdef _DEBUG
}catch(CAbException &e) {
Error(e.GetMessage().c_str());
}
#endif
return bRet;
}
void mi::Stop()
{
}
void mi::Command(int const i)
{
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
switch(i) {
case celc_About:
AboutBox();
break;
case celc_OpenMixer:
OpenMixer();
break;
}
}
bool mi::DblClkHandler(void *)
{
if(m_pcMixDlg) {
if(m_pcMixDlg->IsOpenOnDblClk()) {
OpenMixer();
return true;
}
else
return false;
}
OpenMixer();
return true;
}
void mi::OpenMixer()
{
try{
if(!m_pcMixDlg) {
m_pcMixDlg=new CMixDlg(m_strMachineName.c_str(),&m_cMixerStatus,m_cszModuleName);
}
if(!m_pcMixDlg->IsWindow()) {
m_pcMixDlg->Init(NULL);
m_pcMixDlg->Create();
}else{
m_pcMixDlg->ShowWindowNormal();
::SetActiveWindow(m_pcMixDlg->GetWndHandle());//m_pcMixDlg->ShowWindow();
}
}catch(CAbException &e){
Error(e.GetMessage().c_str());
}
}
void mi::AboutBox()
{
stringstream stm;
stm <<"mimo's miXo\n\nVersion "<<MIXO_VERSION_MAJOR<<"."<<MIXO_VERSION_MINOR<<" ("<<__DATE__<<")\n\nCopyright (c) mimo@restoel.net\n\n"<<ends;
pCB->MessageBox(stm.str().c_str());
}
void mi::Tick()
{
if(gval.wdPreset != cpaPreset.NoValue)
m_pcMixDlg->LoadPreset(gval.wdPreset);
if(gval.btMode != cpaMode.NoValue)
m_pcMixDlg->SetMode(gval.btMode);
// if( gval.AmpLevel!=paraAmpLevel.NoValue ) m_fAmp=gval.AmpLevel/4096.0f;
}
char const *mi::DescribeValue(int const param, int const value)
{
return NULL;
}
void mi::Error(char const *msg)
{
string strTemp;
strTemp="mimo's miXo Error: ";
strTemp+=msg;
strTemp+="\n[This is an internal bug-please report it to the author]";
pCB->MessageBox(strTemp.c_str());
}
void mi::Initialize()
{
//pCallback = pcallback;
//ReadConfig();
}
//miex class
miex::miex() : CMDKMachineInterfaceEx(),m_pcMI(NULL)
{
}
miex::~miex()
{
}
void miex::AddInput(char const *macname, bool stereo)
{
assert(m_pcMI);
if(macname){
m_pcMI->GetMixer()->AddTrack(macname,stereo);
//TODO->TellWin
}
}
void miex::DeleteInput(char const *macname)
{
assert(m_pcMI);
if(macname){
//TODO->TellWin
m_pcMI->GetMixer()->DeleteTrack(macname);
}
}
void miex::SetInputChannels(char const *macname, bool stereo)
{
assert(m_pcMI);
if(macname){
m_pcMI->GetMixer()->SetTrackInputChannels(macname,stereo);
//TODO->TellWin
}
}
void miex::RenameInput(char const *macoldname, char const *macnewname)
{
assert(m_pcMI);
if(macoldname){
try {
m_pcMI->GetMixer()->RenameTrack(macoldname,macnewname);
}catch(CMiXoException &e){
m_pcMI->Error(e.GetMessage().c_str());
}
}
}
void miex::Input(float *pin,int numsamples,float fAmp)
{
/*
if(!psamples)
return;
*/
m_pcMI->GetMixer()->ProcessInput(pin,numsamples,fAmp);
// m_pcMI->Work(m_pcMI->pCB->GetAuxBuffer(),numsamples,WM_READWRITE);
// m_pcMI->MDKWorkStereo(m_pcMI->pCB->GetAuxBuffer(),numsamples,WM_READWRITE);
// DSP_CopyS2MOneChannel(psamples,m_pcMI->pCB->GetAuxBuffer(),numsamples,1.0);
// m_pcMI->pCB->ADWrite(1,m_pcMI->pCB->GetAuxBuffer(),numsamples);
// }
}
bool miex::HandleInput(int index, int amp, int pan)
{
//#ifdef _DEBUG
// stringstream stm;
// stm << "HandleInput:" << index << " amp=" << amp << " pan=" << pan << ends;
// OutputDebugString(stm.str().c_str());
//#endif
return m_pcMI->GetMixer()->HandleInput(index,amp,pan);
}
/*
bool mi::Work(float *psamples, int numsamples, int const mode)
{
if (mode == WM_WRITE || mode == WM_NOIO)
return false;
if (mode == WM_READ || Amount == 0)
return true;
double const drymix = 1.0 - Amount;
float const clamp = (float)(Amount * Clamp);
double const threshold = Threshold;
float negclamp;
double negthreshold;
if (aval.symmetric)
{
negthreshold = -threshold;
negclamp = -clamp;
}
else
{
negthreshold = NegThreshold;
negclamp = (float)(Amount * NegClamp);
}
if (drymix < 0.001)
{
do
{
double const s = *psamples;
if (s >= threshold)
*psamples = clamp;
else if (s <= negthreshold)
*psamples = negclamp;
psamples++;
} while(--numsamples);
}
else
{
do
{
double const s = *psamples;
if (s >= threshold)
*psamples = (float)(s * drymix + clamp);
else if (s <= negthreshold)
*psamples = (float)(s * drymix + negclamp);
psamples++;
} while(--numsamples);
}
return true;
}
*/
//
//void mi::OutputModeChanged(bool stereo)
//{
// stringstream stm;
// stm << "OutputModeChanged:" << stereo << ends;
// OutputDebugString(stm.str().c_str());
//}
// switch(mode){
// case WM_READWRITE:
// OutputDebugString("WM_READWRITE");
// break;
// case WM_READ:
// OutputDebugString("WM_READ");
// break;
// case WM_WRITE:
// OutputDebugString("WM_WRITE");
// break;
// }
// if(m_cMixerStatus.IsUpdateFlagSet())
// OutputDebugString("Update!");
// }
// return false;
//}
// DSP_CopyM2S(pin,pout,numsamples);
// stringstream stm;
//
// stm << "WorkMonoToStereo:" << " p=" << pin << " n=" << numsamples << " mode= " << mode << ends;
// OutputDebugString(stm.str().c_str());
// return false;
/*
bool mi::Work(float *psamples, int numsamples, int const mode)
{
#ifdef _DEBUG
int iTrack=GetMixer()->GetCurrentTrack();
return true;
stringstream stm;
stm << "MDKWORK:" << " p=" << psamples << " n=" << numsamples << " mode= " << mode << "Track="<<iTrack<<ends;
OutputDebugString(stm.str().c_str());
#endif
return false;
//// return MDKWorkStereo(psamples,numsamples,mode);
}
*/
/*
bool mi::WorkStereo(float *psamples, int numsamples, int const mode)
{
// return CMDKMachineInterface::MDKWorkStereo(psamples,numsamples,mode);
#ifdef _DEBUG
int iTrack=GetMixer()->GetCurrentTrack();
stringstream stm;
stm << "MDKWorkStereo:" << " p=" << psamples << " n=" << numsamples << " mode= " << mode << "Track="<<iTrack<<ends;
OutputDebugString(stm.str().c_str());
#endif
return false;;
}
*/
// Handle special flag cases. If we can't write to the buffer, return a proper result based on whether
// we could read from it. This is necessary for <thru> patterns.
// if( (mode&WM_WRITE)==0 )
// return mode&WM_READ?true:false;
//
// // Effect follows. We know we can write to the buffer.
// // numsamples are the number of left,right pairs in the buffer (interleaved left,right)
////
// if( (mode&WM_READ)==0 )
// {
// // We can't read from the buffer so we can't do anything in this effect. Other effects such as reverb and echo
// // could still work in this case, and can just zero the buffer here.
//// return false; // Tell Buzz we haven't produced any output.
// }
// else
// {
///*
//#ifdef _DEBUG
// stringstream stm;
// stm << "dd:";
// for(unsigned u=0;u<numsamples;u++){
// stm << psamples[u] << " ";
// }
//// OutputDebugString(stm.str().c_str());
//#endif
//*/
// // We can read and write to the buffer. Run our effect. numsamples*2 because of interleaved sampledata
//// DSP_Copy(m_pcMI->pCB->GetAuxBuffer(),psamples,numsamples);
//// //DSP_Copy(pCB->GetAuxBuffer(),psamples,numsamples);
// return true; // Tell Buzz we made some noise.
// //return false;
// }
//}
////Command-Method: Implementation of own Context-Menu-Functions
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -