-
-
Save severak/097a2df095c99c8be6fd7e1d06056233 to your computer and use it in GitHub Desktop.
Polyvalens VL-1 clone source code excerpts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __VL1_DEFS_H__ | |
#define __VL1_DEFS_H__ | |
#ifndef NULL | |
#define NULL 0 | |
#endif // NULL | |
#ifndef FALSE | |
#define FALSE 0 | |
#endif // FALSE | |
#ifndef TRUE | |
#define TRUE (!FALSE) | |
#endif // TRUE | |
#ifndef BOOL | |
typedef int BOOL; | |
#endif // BOOL | |
// ASIC clock | |
const float kAsicClock = 200000.0f; // Hz | |
const float kTempoUnit = 0.034f; // sec | |
const float kMinTempoPeriod = 0.170f; // sec | |
const float kPi = 3.141592654f; | |
#define kWhole 32 | |
#define kHalf (kWhole/2) | |
#define kQuarter (kWhole/4) | |
#define kEighth (kWhole/8) | |
#define kSixteenth (kWhole/16) | |
#define kThirtytwoth (kWhole/32) | |
#define kDefaultSampleRate 44100 | |
#define kDefaultOversampling 16 | |
// Constants | |
enum | |
{ | |
// Global | |
kNumOutputs = 2, | |
kWaveTableSize = 32, //4096, | |
// Modes | |
kVL1Play = 0, | |
kVL1Rec, | |
kVL1Cal, | |
kVL1Off, | |
kProgramPiano = (char)0, | |
kProgramFantasy = (char)1, | |
kProgramViolin = (char)2, | |
kProgramFlute = (char)3, | |
kProgramGuitar = (char)4, | |
kProgramAdsr = (char)5, | |
kNumPrograms, // This should always be the last program. | |
// Casio parameters for sounds. | |
kParamsPiano = 453200, | |
kParamsFantasy = 10099630, | |
kParamsViolin = 23099130, | |
kParamsFlute = 33099130, | |
kParamsGuitar = 41071200, | |
// Sounds | |
kPiano = 0, | |
kFantasy = 1, | |
kViolin = 2, | |
kFlute = 3, | |
kGuitar1 = 4, | |
kGuitar2 = 5, | |
kEnglishHorn = 6, | |
kElectro1 = 7, | |
kElectro2 = 8, | |
kElectro3 = 9, | |
kNumSounds, | |
kSinc, | |
kADSR = 10, | |
// Rhythm sounds. | |
kPock = 0, // About 750 Hz square wave. | |
kPeek, // kPock at double speed. | |
kNoise, // Noise with "complicated" envelope. | |
kMaxRhythmSound, | |
// Rhythms. | |
kNoRhythm = -1, | |
kMarch = 0, | |
kWaltz, | |
k4Beat, | |
kSwing, | |
kRock1, | |
kRock2, | |
kBossanova, | |
kSamba, | |
kRhumba, | |
kBeguine, | |
kMaxRhythm, | |
// Parameters Tags | |
// The order is important for the display in the host. | |
kProgram = 0, | |
kMode, | |
kVolume, | |
kBalance, | |
kOctave, | |
kTune, | |
kSound, | |
kAttack, | |
kDecay, | |
kSustainLevel, | |
kSustainTime, | |
kRelease, | |
kVibrato, | |
kTremolo, | |
kTempo, | |
kNumParams, // This should always be the last parameter. | |
// Keyboard | |
kKeyPlusMin = 55, | |
kKeyPlusMinS = 56, | |
kKeyDot = 57, | |
kKeyDotS = 58, | |
kKey0 = 59, | |
kKey1 = 60, // Middle C | |
kKey1S = 61, | |
kKey2 = 62, | |
kKey2S = 63, | |
kKey3 = 64, | |
kKey4 = 65, | |
kKey4S = 66, | |
kKey5 = 67, | |
kKey5S = 68, | |
kKey6 = 69, | |
kKey6S = 70, | |
kKey7 = 71, | |
kKey8 = 72, | |
kKey8S = 73, | |
kKey9 = 74, | |
kKey9S = 75, | |
kKeyDiv = 76, | |
kKeyMul = 77, | |
kKeyMulS = 78, | |
kKeySub = 79, | |
kKeySubS = 80, | |
kKeyAdd = 81, | |
kKeyAddS = 82, | |
kKeyEqual = 83, | |
kKeyReset, | |
kKeyDel, | |
kKeyTempoUp, | |
kKeyTempoDown, | |
kKeyRhythm, | |
kKeyMLC, | |
kKeyMusic, | |
kKeyAutoPlay, | |
kKeyOneKeyPlayDotDot, | |
kKeyOneKeyPlayDot, | |
//kDisplay, | |
kChar1, | |
kChar2, | |
kChar3, | |
kChar4, | |
kChar5, | |
kChar6, | |
kChar7, | |
kChar8, | |
kChar9, | |
kSharp1, | |
kSharp2, | |
kSharp3, | |
kDot1, | |
kDot2, | |
kDot3, | |
kDot4, | |
kDot5, | |
kDot6, | |
kDot7, | |
kDot8, | |
kAdd, | |
kSub, | |
kDiv, | |
kMul, | |
kK, | |
kM, | |
kErr, | |
}; | |
extern const char *gVL1SoundNames[]; | |
extern const char *gVL1PresetNames[]; | |
typedef float tVL1Preset[8]; | |
const tVL1Preset gVL1Preset[kNumPrograms] = | |
{ | |
// sound A D Sl St R V T | |
{ 0.0f, 0.0f, 0.4f, 0.5f, 0.3f, 0.2f, 0.0f, 0.0f }, // Piano | |
{ 0.1f, 0.0f, 0.0f, 0.9f, 0.9f, 0.6f, 0.3f, 0.0f }, // Fantasy | |
{ 0.2f, 0.3f, 0.0f, 0.9f, 0.9f, 0.1f, 0.3f, 0.0f }, // Violin | |
{ 0.3f, 0.3f, 0.0f, 0.9f, 0.9f, 0.1f, 0.3f, 0.0f }, // Fute | |
{ 0.4f, 0.1f, 0.0f, 0.7f, 0.1f, 0.2f, 0.0f, 0.0f }, // Guitar | |
{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, // ADSR | |
}; | |
// Envelopes | |
// --------- | |
// An envelope can take on at most 15 different levels (not counting 0). | |
// Envelope time is discrete. | |
// An envelope phase (A, D, S or R) is linear and can be defined by | |
// a start level, a stop level and the number of time units. | |
const float kEnvelopeDivisor = 2400.0f; | |
const float kEnvelopeTimeUnit = kEnvelopeDivisor/kAsicClock; // sec | |
const float kEnvelopeLevels = 15.0f; | |
const float kEnvelopeStep = 1.0f/kEnvelopeLevels; | |
typedef struct | |
{ | |
float lBegin; | |
float lEnd; | |
float tUnits; | |
} | |
tEnvelopePhaseInfo; | |
#define kEnvelopeRange 11 // ADSR values go from 0 to 9. | |
const tEnvelopePhaseInfo gAttack[kEnvelopeRange] = | |
{ | |
{ 15.0f, 15.0f, 0.0f }, // 0 | |
{ 11.0f, 15.0f, 1.0f }, // 1 | |
{ 7.0f, 15.0f, 4.0f }, // 2 | |
{ 5.0f, 15.0f, 7.0f }, // 3 | |
{ 4.0f, 15.0f, 10.0f }, // 4 | |
{ 4.0f, 15.0f, 13.0f }, // 5 | |
{ 3.0f, 15.0f, 16.0f }, // 6 | |
{ 3.0f, 15.0f, 19.0f }, // 7 | |
{ 3.0f, 15.0f, 22.0f }, // 8 | |
{ 3.0f, 15.0f, 25.0f }, // 9 | |
{ 2.0f, 15.0f, 28.0f }, // 10 | |
}; | |
const tEnvelopePhaseInfo gDecay[kEnvelopeRange] = | |
{ | |
{ 15.0f, 0.0f, 0.0f }, // 0 | |
{ 15.0f, 0.0f, 9.0f }, // 1 | |
{ 15.0f, 0.0f, 18.0f }, // 2 | |
{ 15.0f, 0.0f, 27.0f }, // 3 | |
{ 15.0f, 0.0f, 39.0f }, // 4 | |
{ 15.0f, 0.0f, 48.0f }, // 5 | |
{ 15.0f, 0.0f, 58.0f }, // 6 | |
{ 15.0f, 0.0f, 67.0f }, // 7 | |
{ 15.0f, 0.0f, 78.0f }, // 8 | |
{ 15.0f, 0.0f, 87.0f }, // 9 | |
{ 15.0f, 0.0f, 98.0f }, // 10 | |
}; | |
const tEnvelopePhaseInfo gSustainLevel[kEnvelopeRange] = | |
{ | |
{ 15.0f, 1.0f, 0.0f }, // 0 | |
{ 15.0f, 2.0f, 0.0f }, // 1 | |
{ 15.0f, 4.0f, 0.0f }, // 2 | |
{ 15.0f, 6.0f, 0.0f }, // 3 | |
{ 15.0f, 8.0f, 0.0f }, // 4 | |
{ 15.0f, 10.0f, 0.0f }, // 5 | |
{ 15.0f, 12.0f, 0.0f }, // 6 | |
{ 15.0f, 13.0f, 0.0f }, // 7 | |
{ 15.0f, 14.0f, 0.0f }, // 8 | |
{ 15.0f, 15.0f, 0.0f }, // 9 | |
{ 15.0f, 15.0f, 0.0f }, // 10 | |
}; | |
const tEnvelopePhaseInfo gSustainSlope[kEnvelopeRange] = | |
{ | |
{ 15.0f, 0.0f, 0.0f }, // 0 | |
{ 15.0f, 0.0f, 79.0f }, // 1 | |
{ 15.0f, 0.0f, 154.0f }, // 2 | |
{ 15.0f, 0.0f, 231.0f }, // 3 | |
{ 15.0f, 0.0f, 312.0f }, // 4 | |
{ 15.0f, 0.0f, 389.0f }, // 5 | |
{ 15.0f, 0.0f, 467.0f }, // 6 | |
{ 15.0f, 0.0f, 543.0f }, // 7 | |
{ 15.0f, 0.0f, 615.0f }, // 8 | |
{ 15.0f, 0.0f, -1.0f }, // 9, infinite | |
{ 15.0f, 0.0f, -1.0f }, // 10, infinite | |
}; | |
const tEnvelopePhaseInfo gRelease[kEnvelopeRange] = | |
{ | |
{ 14.0f, 0.0f, 0.0f }, // 0 | |
{ 14.0f, 0.0f, 26.0f }, // 1 | |
{ 14.0f, 0.0f, 48.0f }, // 2 | |
{ 14.0f, 0.0f, 73.0f }, // 3 | |
{ 14.0f, 0.0f, 96.0f }, // 4 | |
{ 14.0f, 0.0f, 116.0f }, // 5 | |
{ 14.0f, 0.0f, 142.0f }, // 6 | |
{ 14.0f, 0.0f, 167.0f }, // 7 | |
{ 14.0f, 0.0f, 193.0f }, // 8 | |
{ 14.0f, 0.0f, 217.0f }, // 9 | |
{ 14.0f, 0.0f, 242.0f }, // 10 | |
}; | |
#endif // __VL1_DEFS_H__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "VL1Defs.h" | |
#include "Utils.h" | |
#include "Wave.h" | |
#include "GlobalData.h" | |
#include <math.h> | |
CWave::CWave() : | |
m_pData(NULL), | |
m_size(0), | |
m_pitchScale(1.0f) | |
{ | |
} | |
CWave::CWave(int type, int size) | |
{ | |
Create(type,size); | |
} | |
CWave::~CWave() | |
{ | |
if (m_pData) delete [] m_pData; | |
m_pData = NULL; | |
} | |
#include <stdio.h> | |
void CWave::DumpToFile(char *pFilePath) | |
{ | |
int n = 1; //10 | |
FILE *f = fopen(pFilePath,"wb"); | |
if (f) | |
{ | |
for (int i=0; i<n; i++) | |
{ | |
fwrite(m_pData,m_size,sizeof(float),f); | |
} | |
fclose(f); | |
} | |
} | |
void CWave::Create(int type, int size, float width) | |
{ | |
//* | |
BOOL bWriteFile = TRUE; | |
/*/ | |
BOOL bWriteFile = FALSE; | |
/*/ | |
if ((m_pData) && (size!=m_size/gOversampling)) | |
{ | |
delete [] m_pData; | |
m_pData = NULL; | |
} | |
if (!m_pData) m_pData = new float[size*(int)gOversampling]; | |
if (m_pData) | |
{ | |
m_size = size*(int)gOversampling; | |
memset(m_pData,0,m_size*sizeof(float)); | |
switch (type) | |
{ | |
case kPiano: | |
MakePiano(); | |
if (bWriteFile) DumpToFile("piano.raw"); | |
break; | |
case kFantasy: | |
MakeFantasy(); | |
if (bWriteFile) DumpToFile("fantasy.raw"); | |
break; | |
case kViolin: | |
MakeViolin(); | |
if (bWriteFile) DumpToFile("violin.raw"); | |
break; | |
case kFlute: | |
MakeFlute(); | |
if (bWriteFile) DumpToFile("flute.raw"); | |
break; | |
case kGuitar1: | |
MakeGuitar1(); | |
if (bWriteFile) DumpToFile("guitar1.raw"); | |
break; | |
case kGuitar2: | |
MakeGuitar2(); | |
if (bWriteFile) DumpToFile("guitar2.raw"); | |
break; | |
case kEnglishHorn: | |
MakeEnglishHorn(); | |
if (bWriteFile) DumpToFile("horn.raw"); | |
break; | |
//case kWaveNoise: | |
// MakeNoise(); | |
//break; | |
case kSinc: | |
MakeSinc(width); | |
if (bWriteFile) DumpToFile("sinc.raw"); | |
break; | |
} | |
} | |
} | |
const float _PI_ = (float)(4.0*atan(1.0)); | |
const float _2PI_ = (float)(8.0*atan(1.0)); | |
void CWave::MakeSinc(float width) // width as a fraction of T (m_size) | |
{ | |
float dt = _2PI_/(width*(float)m_size); | |
float dt2 = _PI_/(float)m_size; | |
int dx = 0.5*m_size; | |
for (int i=0; i<m_size; i++) | |
{ | |
float t = (float)(i-dx)*dt; | |
if (t!=0.0f) m_pData[i] = sinf(t)/t; | |
else m_pData[i] = 1.0f; | |
m_pData[i] *= sinf((float)i*dt2); | |
} | |
} | |
void CWave::MakePulse(float dutyCycle) | |
{ | |
int i; | |
int size = m_size; | |
float h0 = dutyCycle*size; | |
//float h1 = 1.02*dutyCycle*size; | |
for (i=0; i<(int)h0; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
/*for (; i<(int)h1; i++) | |
{ | |
m_pData[i] = 1.0 - 2.0*(i-h0)/(h1-h0); | |
}*/ | |
for (; i<size; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
} | |
void CWave::MakePiano() | |
{ | |
MakePulse(11.0f/16.0f); | |
m_pitchScale = 1.0f; | |
} | |
void CWave::MakeFantasy() | |
{ | |
MakePulse(0.5f); | |
m_pitchScale = 2.0f; | |
} | |
//* | |
void CWave::MakeViolin() | |
{ | |
long i; | |
long size = m_size; | |
for (i=0; i<(4*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<(5*size)/16; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
for (; i<(8*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<(9*size)/16; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
for (; i<(11*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<(12*size)/16; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
for (; i<(13*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<(14*size)/16; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
for (; i<(15*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<size; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
m_pitchScale = 1.0f; | |
} | |
/*/ | |
#include <math.h> | |
void CWave::MakeViolin() | |
{ | |
long i; | |
long size = m_size; | |
float max = -100.0f; | |
float min = 100.0f; | |
for (i=0; i<size; i++) | |
{ | |
float w = 2.0f*kPi*(float)i/(float)size; | |
m_pData[i] = 0.298f*sinf(w); | |
m_pData[i] += 0.098f*sinf(3.0f*w); | |
m_pData[i] += 0.058f*sinf(5.0f*w); | |
m_pData[i] += 0.042f*sinf(7.0f*w); | |
m_pData[i] += 0.033f*sinf(9.0f*w); | |
if (m_pData[i]>max) max = m_pData[i]; | |
if (m_pData[i]<min) min = m_pData[i]; | |
} | |
for (i=0; i<size; i++) | |
{ | |
m_pData[i] = (m_pData[i]-min)/(max-min); | |
} | |
m_pitchScale = 1.0f; | |
} | |
//*/ | |
void CWave::MakeFlute() | |
{ | |
MakePulse(0.5f); | |
m_pitchScale = 1.0f; | |
} | |
void CWave::MakeGuitar1() | |
{ | |
long i; | |
long size = m_size; | |
for (i=0; i<size/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<(7*size)/16; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
for (; i<(8*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<size; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
m_pitchScale = 0.5f; | |
} | |
void CWave::MakeGuitar2() | |
{ | |
long i; | |
long size = m_size; | |
for (i=0; i<size/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<(2*size)/16; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
for (; i<(6*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<(8*size)/16; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
for (; i<(10*size)/16; i++) | |
{ | |
m_pData[i] = 1.0f; | |
} | |
for (; i<size; i++) | |
{ | |
m_pData[i] = 0.0f; | |
} | |
m_pitchScale = 0.5f; | |
} | |
void CWave::MakeEnglishHorn() | |
{ | |
MakePulse(1.0f/7.0f); | |
m_pitchScale = 0.5f; | |
} | |
/*void CWave::MakeNoise() | |
{ | |
m_pitchScale = 1.0f; | |
}*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment