⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mixo_mi.cpp

📁 miXo is a buzz machine (www.buzzmachines.com) - a plugin for the freely available jeskola buzz track
💻 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 + -