Merge branch 'master' into newFilePicker
This commit is contained in:
commit
5110538c3f
5 changed files with 96 additions and 127 deletions
23
doc/7-systems/multipcm.md
Normal file
23
doc/7-systems/multipcm.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Yamaha YMW258-F (MultiPCM)
|
||||
|
||||
a sound chip introduced in 1991 by Yamaha for their first General MIDI-compliant synthesizer, the Yamaha TG100. It also appeared on a number of higher-end consumer keyboards and specialized professional devices. The YMW258-F implements the GEW8 sound synthesis technology, which is PCM sample-based synthesis under Yamaha's "Advanced Wave Modulation" (AWM) umbrella.
|
||||
|
||||
Sega used the chip in several arcade games on the Sega System Multi 32, Sega Model 1, and Sega Model 2 arcade boards. The chip as found on these boards is called MultiPCM, and has the Sega internal part number 315-5560. Contrary to popular belief, it is not a custom Sega part and is not based on the earlier SegaPCM chip, but it was named the MultiPCM as a successor to that chip.
|
||||
|
||||
it has a whopping 28 channels of stereo 16-bit PCM and:
|
||||
|
||||
- hardware LFO
|
||||
- 8bit and 12bit wave format support
|
||||
- up to 4MB of wave memory
|
||||
- full blown ADSR envelopes
|
||||
|
||||
## effects
|
||||
|
||||
- `20xx`: **set PCM LFO rate.**
|
||||
- `21xx`: **set PCM LFO PM depth..**
|
||||
- `22xx`: **set PCM LFO AM depth.**
|
||||
|
||||
|
||||
## info
|
||||
|
||||
this chip uses the [MultiPCM](../4-instrument/multipcm.md) instrument editor.
|
||||
|
|
@ -1279,8 +1279,8 @@ SafeWriter* DivEngine::saveDMF(unsigned char version) {
|
|||
for (int i=0; i<chans; i++) {
|
||||
for (int j=0; j<curSubSong->ordersLen; j++) {
|
||||
if (curOrders->ord[i][j]>0x7f) {
|
||||
logE("order %d, %d is out of range (0-127)!",curOrders->ord[i][j]);
|
||||
lastError=fmt::sprintf("order %d, %d is out of range (0-127)",curOrders->ord[i][j]);
|
||||
logE("order %d, %d is out of range (0-127)!",i,j);
|
||||
lastError=fmt::sprintf("order %d, %d is out of range (0-127)",i,j);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -618,90 +618,14 @@ void FurnaceGUI::drawFindReplace() {
|
|||
if ((i.noteMode==GUI_QUERY_RANGE || i.noteMode==GUI_QUERY_RANGE_NOT) && i.note>=120) {
|
||||
i.note=0;
|
||||
}
|
||||
if (i.note==130) {
|
||||
snprintf(tempID,1024,"%s##MREL",macroRelLabel);
|
||||
} else if (i.note==129) {
|
||||
snprintf(tempID,1024,"%s##NREL",noteRelLabel);
|
||||
} else if (i.note==128) {
|
||||
snprintf(tempID,1024,"%s##NOFF",noteOffLabel);
|
||||
} else if (i.note>=-60 && i.note<120) {
|
||||
snprintf(tempID,1024,"%c%c",noteNames[i.note+60][0],(noteNames[i.note+60][1]=='-')?' ':noteNames[i.note+60][1]);
|
||||
} else {
|
||||
snprintf(tempID,1024,"???");
|
||||
i.note=0;
|
||||
}
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x/2);
|
||||
bool updateNote1=false;
|
||||
int note1=i.note%12;
|
||||
int oct1=i.note/12;
|
||||
if (ImGui::BeginCombo("##NN1",tempID)) {
|
||||
for (int j=0; j<12; j++) {
|
||||
snprintf(tempID,1024,"%c%c",noteNames[j+72][0],(noteNames[j+72][1]=='-')?' ':noteNames[j+72][1]);
|
||||
if (ImGui::Selectable(tempID,note1==j)) {
|
||||
note1=j;
|
||||
updateNote1=true;
|
||||
}
|
||||
}
|
||||
if (i.noteMode!=GUI_QUERY_RANGE && i.noteMode!=GUI_QUERY_RANGE_NOT) {
|
||||
if (ImGui::Selectable(noteOffLabel,note1==13)) {
|
||||
i.note=128;
|
||||
}
|
||||
if (ImGui::Selectable(noteRelLabel,note1==14)) {
|
||||
i.note=129;
|
||||
}
|
||||
if (ImGui::Selectable(macroRelLabel,note1==15)) {
|
||||
i.note=130;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (i.note<128) {
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x/2);
|
||||
if (ImGui::InputScalar("##NNO1",ImGuiDataType_S32,&oct1)) {
|
||||
if (oct1<-5) oct1=-5;
|
||||
if (oct1>9) oct1=9;
|
||||
updateNote1=true;
|
||||
}
|
||||
}
|
||||
if (updateNote1) {
|
||||
i.note=oct1*12+note1;
|
||||
}
|
||||
NoteSelector(&i.note, i.noteMode!=GUI_QUERY_RANGE && i.noteMode!=GUI_QUERY_RANGE_NOT);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
if (SECOND_VISIBLE(i.noteMode)) {
|
||||
if (i.noteMax<-60 || i.noteMax>=120) {
|
||||
i.noteMax=0;
|
||||
}
|
||||
if (i.noteMax>=-60 && i.noteMax<120) {
|
||||
snprintf(tempID,1024,"%c%c",noteNames[i.noteMax+60][0],(noteNames[i.noteMax+60][1]=='-')?' ':noteNames[i.noteMax+60][1]);
|
||||
} else {
|
||||
snprintf(tempID,1024,"???");
|
||||
}
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x/2);
|
||||
bool updateNote2=false;
|
||||
int note2=i.noteMax%12;
|
||||
int oct2=i.noteMax/12;
|
||||
if (ImGui::BeginCombo("##NN2",tempID)) {
|
||||
for (int j=0; j<12; j++) {
|
||||
snprintf(tempID,1024,"%c%c",noteNames[j+72][0],(noteNames[j+72][1]=='-')?' ':noteNames[j+72][1]);
|
||||
if (ImGui::Selectable(tempID,note2==j)) {
|
||||
note2=j;
|
||||
updateNote2=true;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x/2);
|
||||
if (ImGui::InputScalar("##NNO2",ImGuiDataType_S32,&oct2)) {
|
||||
if (oct2<-5) oct2=-5;
|
||||
if (oct2>9) oct2=9;
|
||||
updateNote2=true;
|
||||
}
|
||||
if (updateNote2) {
|
||||
i.noteMax=oct2*12+note2;
|
||||
}
|
||||
NoteSelector(&i.noteMax, false);
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
|
@ -912,53 +836,7 @@ void FurnaceGUI::drawFindReplace() {
|
|||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (queryReplaceNoteMode==GUI_QUERY_REPLACE_SET) {
|
||||
if (queryReplaceNote==130) {
|
||||
snprintf(tempID,1024,"%s##MREL",macroRelLabel);
|
||||
} else if (queryReplaceNote==129) {
|
||||
snprintf(tempID,1024,"%s##NREL",noteRelLabel);
|
||||
} else if (queryReplaceNote==128) {
|
||||
snprintf(tempID,1024,"%s##NOFF",noteOffLabel);
|
||||
} else if (queryReplaceNote>=-60 && queryReplaceNote<120) {
|
||||
snprintf(tempID,1024,"%c%c",noteNames[queryReplaceNote+60][0],(noteNames[queryReplaceNote+60][1]=='-')?' ':noteNames[queryReplaceNote+60][1]);
|
||||
} else {
|
||||
snprintf(tempID,1024,"???");
|
||||
queryReplaceNote=0;
|
||||
}
|
||||
bool updateNote=false;
|
||||
int note1=queryReplaceNote%12;
|
||||
int oct1=queryReplaceNote/12;
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x/2);
|
||||
if (ImGui::BeginCombo("##NRValueC",tempID)) {
|
||||
for (int i=0; i<12; i++) {
|
||||
snprintf(tempID,1024,"%c%c",noteNames[i+72][0],(noteNames[i+72][1]=='-')?' ':noteNames[i+72][1]);
|
||||
if (ImGui::Selectable(tempID,note1==i)) {
|
||||
note1=i;
|
||||
updateNote=true;
|
||||
}
|
||||
}
|
||||
if (ImGui::Selectable(noteOffLabel,note1==13)) {
|
||||
queryReplaceNote=128;
|
||||
}
|
||||
if (ImGui::Selectable(noteRelLabel,note1==14)) {
|
||||
queryReplaceNote=129;
|
||||
}
|
||||
if (ImGui::Selectable(macroRelLabel,note1==15)) {
|
||||
queryReplaceNote=130;
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (queryReplaceNote<128) {
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x/2);
|
||||
if (ImGui::InputScalar("##NRValueCO",ImGuiDataType_S32,&oct1)) {
|
||||
if (oct1<-5) oct1=-5;
|
||||
if (oct1>9) oct1=9;
|
||||
updateNote=true;
|
||||
}
|
||||
}
|
||||
if (updateNote) {
|
||||
queryReplaceNote=oct1*12+note1;
|
||||
}
|
||||
NoteSelector(&queryReplaceNote, true);
|
||||
} else if (queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD || queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) {
|
||||
if (ImGui::InputInt("##NRValue",&queryReplaceNote,1,12)) {
|
||||
if (queryReplaceNote<-180) queryReplaceNote=-180;
|
||||
|
|
|
|||
|
|
@ -535,6 +535,72 @@ bool FurnaceGUI::InvCheckbox(const char* label, bool* value) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool FurnaceGUI::NoteSelector(int* value, bool showOffRel, int octaveMin, int octaveMax) {
|
||||
bool ret=false, calcNote=false;
|
||||
char tempID[64];
|
||||
if (*value==130) {
|
||||
snprintf(tempID,64,"%s##MREL",macroRelLabel);
|
||||
} else if (*value==129) {
|
||||
snprintf(tempID,64,"%s##NREL",noteRelLabel);
|
||||
} else if (*value==128) {
|
||||
snprintf(tempID,64,"%s##NOFF",noteOffLabel);
|
||||
} else if (*value>=-60 && *value<120) {
|
||||
snprintf(tempID,64,"%c%c",noteNames[*value%12+72][0],(noteNames[*value%12+72][1]=='-')?' ':noteNames[*value%12+72][1]);
|
||||
} else {
|
||||
snprintf(tempID,64,"???");
|
||||
*value=0;
|
||||
}
|
||||
float width=ImGui::GetContentRegionAvail().x/2-ImGui::GetStyle().FramePadding.x;
|
||||
ImGui::SetNextItemWidth(width);
|
||||
int note=(*value+60)%12;
|
||||
int oct=0;
|
||||
if (*value<120) oct=(*value-note)/12;
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushID(value);
|
||||
if (ImGui::BeginCombo("##NoteSelectorNote",tempID)) {
|
||||
for (int j=0; j<12; j++) {
|
||||
snprintf(tempID,64,"%c%c",noteNames[j+72][0],(noteNames[j+72][1]=='-')?' ':noteNames[j+72][1]);
|
||||
if (ImGui::Selectable(tempID,note==j && *value<128)) {
|
||||
note=j;
|
||||
calcNote=true;
|
||||
}
|
||||
if (note==j && *value<120) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
if (showOffRel) {
|
||||
if (ImGui::Selectable(noteOffLabel,*value==128)) {
|
||||
*value=128;
|
||||
ret=true;
|
||||
}
|
||||
if (ImGui::Selectable(noteRelLabel,*value==129)) {
|
||||
*value=129;
|
||||
ret=true;
|
||||
}
|
||||
if (ImGui::Selectable(macroRelLabel,*value==130)) {
|
||||
*value=130;
|
||||
ret=true;
|
||||
}
|
||||
if (*value>=128 && *value<=130) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (*value<120) {
|
||||
ImGui::SetNextItemWidth(width/2);
|
||||
if (ImGui::InputScalar("##NoteSelectorOctave",ImGuiDataType_S32,&oct)) {
|
||||
if (oct<octaveMin) oct=octaveMin;
|
||||
if (oct>octaveMax) oct=octaveMax;
|
||||
calcNote=true;
|
||||
}
|
||||
}
|
||||
if (calcNote) {
|
||||
*value=oct*12+note;
|
||||
ret=true;
|
||||
}
|
||||
ImGui::PopID();
|
||||
ImGui::EndGroup();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FurnaceGUI::LocalizedComboGetter(void* data, int idx, const char** out_text) {
|
||||
const char* const* items=(const char* const*)data;
|
||||
if (out_text) *out_text=_(items[idx]);
|
||||
|
|
|
|||
|
|
@ -2871,6 +2871,8 @@ class FurnaceGUI {
|
|||
// inverted checkbox
|
||||
bool InvCheckbox(const char* label, bool* value);
|
||||
|
||||
bool NoteSelector(int* value, bool showOffRel, int octaveMin=-5, int octaveMax=9);
|
||||
|
||||
// mixer stuff
|
||||
ImVec2 calcPortSetSize(String label, int ins, int outs);
|
||||
bool portSet(String label, unsigned int portSetID, int ins, int outs, int activeIns, int activeOuts, int& clickedPort, std::map<unsigned int,ImVec2>& portPos);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue