Skip to content

Commit

Permalink
Support Slur/Tie & command #7
Browse files Browse the repository at this point in the history
  • Loading branch information
kujirahand committed Aug 4, 2023
1 parent a301aaf commit 5f9236e
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 120 deletions.
10 changes: 5 additions & 5 deletions src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub fn lex(song: &mut Song, src: &str, lineno: isize) -> Vec<Token> {
'`' => result.push(Token::new_value(TokenType::OctaveOnce, 1)), // @ 一度だけ音階を+1する
'"' => result.push(Token::new_value(TokenType::OctaveOnce, -1)), // @ 一度だけ音階を-1する
'?' => result.push(Token::new_value(TokenType::PlayFrom, 0)), // @ ここから演奏する (=PLAY_FROM)
'&' => {} // @ タイ(todo: 現在未実装)
'&' => {}, // @ タイ・スラー(Slurコマンドで動作が変更できる)
// </CHAR_COMMANDS>
_ => {
if song.logs.len() == LEX_MAX_ERROR {
Expand Down Expand Up @@ -193,12 +193,12 @@ fn read_upper_command(cur: &mut TokenCursor, song: &mut Song) -> Token {
return Token::new_value(TokenType::TrackSync, 0);
}
if cmd == "SLUR" || cmd == "Slur" {
// @ 未実装
// @ タイ・スラー記号(&)の動作を変更する(0:グリッサンド/1:ベンド/2:ゲート/3:アルペジオ)
let args: SValue = read_arg_value_int_array(cur, song);
return Token::new(
TokenType::Empty,
TokenType::TieMode,
0,
read_arg_int_array(cur, song).to_array(),
);
vec![args]);
}
if cmd == "System.Include" || cmd == "Include" || cmd == "INCLUDE" {
// @ 未実装
Expand Down
31 changes: 29 additions & 2 deletions src/midi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
/// midi
use super::song::{Song, Track, EventType};

/// MIDI Event
const MIDI_RPN_MSB: u8 = 0x65;
const MIDI_RPN_LSB: u8 = 0x64;
const MIDI_DATA_ENTRY_MSB: u8 = 0x06;
const _MIDI_DATA_ENTRY_LSB: u8 = 0x26;

fn array_push_str(res: &mut Vec<u8>, s: &str) {
for b in s.as_bytes() {
res.push(*b);
Expand Down Expand Up @@ -115,14 +121,35 @@ fn generate_track(track: &Track) -> Vec<u8> {
res.push(0xE0 + e.channel as u8);
res.push(lsb);
res.push(msb);
},
EventType::PitchBendRange => { // RPN
// Pitch Bend Sensitivity (3 events)
let range = e.v1;
let range = if range >= 0 && range <= 24 { range as u8 } else { 0 };
// RPN MSB
array_push_delta(&mut res, e.time - timepos);
timepos = e.time;
res.push(0xB0 + e.channel as u8);
res.push(MIDI_RPN_MSB);
res.push(0);
// RPN LSB
res.push(0);
res.push(0xB0 + e.channel as u8);
res.push(MIDI_RPN_LSB);
res.push(0);
// Data Entry MSB
res.push(0);
res.push(0xB0 + e.channel as u8);
res.push(MIDI_DATA_ENTRY_MSB);
res.push(range);
}
}
}
// end of track
res.push(00);
res.push(0x00);
res.push(0xFF);
res.push(0x2F);
res.push(00);
res.push(0x00);
res
}

Expand Down
40 changes: 18 additions & 22 deletions src/mml_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ use crate::sakura_version;
use crate::svalue::SValue;
use std::collections::HashMap;

// Tie & Slur Mode
pub const TIE_MODE_PORT: isize = 0; // グリッサンド : ノートオンを、ポルタメントでつなぐ
pub const TIE_MODE_BEND: isize = 1; // 異音程をベンドで表現、ギターのハンマリングに近い : ノートオンを、ベンドでつなぐ
pub const TIE_MODE_GATE: isize = 2; // ノートオンのゲートを100%にする ( &のついた音符のゲートを、valueにする ... )
pub const TIE_MODE_ALPE: isize = 3; // &でつないだ音符の終わりまでゲートを伸ばす。どんどん重なる。

pub fn init_rhythm_macro() -> Vec<String> {
// Rhythm macro ... 1 char macro
let mut rhthm_macro: Vec<String> = vec![];
Expand All @@ -27,27 +33,17 @@ pub fn init_rhythm_macro() -> Vec<String> {
pub fn init_variables() -> HashMap<String, SValue> {
let mut var = HashMap::new();
//<VARIABLES>
var.insert(
String::from("SAKURA_VERSION"),
SValue::from_s(sakura_version::SAKURA_VERSION.to_string()),
); // @ サクラのバージョン情報を得る
var.insert(
String::from("OctaveUnison"),
SValue::from_str("Sub{> #?1 <} #?1"),
); // @ オクターブユニゾンを演奏 (例 OctaveUnison{cde})
var.insert(
String::from("Unison5th"),
SValue::from_str("Sub{ Key=7 #?1 Key=0 } #?1"),
); // @ 5度のユニゾンを演奏 (例 Unison5th{cde})
var.insert(
String::from("Unison3th"),
SValue::from_str("Sub{ Key=4 #?1 Key=0 } #?1"),
); // @ 3度のユニゾンを演奏 (例 Unison3th{cde})
var.insert(
String::from("Unison"),
SValue::from_str("Sub{ Key=#?2 #?1 Key=0 } #?1"),
); // @ N度のユニゾンを演奏 (例 Unison{cde},7)
//
var.insert(String::from("SAKURA_VERSION"), SValue::from_s(sakura_version::SAKURA_VERSION.to_string())); // @ サクラのバージョン情報を得る
var.insert(String::from("OctaveUnison"), SValue::from_str("Sub{> #?1 <} #?1")); // @ オクターブユニゾンを演奏 (例 OctaveUnison{cde})
var.insert(String::from("Unison5th"), SValue::from_str("Sub{ Key=7 #?1 Key=0 } #?1")); // @ 5度のユニゾンを演奏 (例 Unison5th{cde})
var.insert(String::from("Unison3th"), SValue::from_str("Sub{ Key=4 #?1 Key=0 } #?1")); // @ 3度のユニゾンを演奏 (例 Unison3th{cde})
var.insert(String::from("Unison"), SValue::from_str("Sub{ Key=#?2 #?1 Key=0 } #?1")); // @ N度のユニゾンを演奏 (例 Unison{cde},7)
// tie/slur mode
var.insert(String::from("SlurModePort"), SValue::from_i(0)); // @ SLUR_MODE : グリッサンド。ノートオンを、ポルタメントでつなぐ
var.insert(String::from("SlurModeBend"), SValue::from_i(1)); // @ SLUR_MODE : ベンド。異音程をベンドで表現。ギターのハンマリングに近い。
var.insert(String::from("SlurModeGate"), SValue::from_i(2)); // @ SLUR_MODE : &のついた音符のゲートを、valueにする
var.insert(String::from("SlurModeAlpe"), SValue::from_i(3)); // @ SLUR_MODE : &でつないだ音符の終わりまでゲートを伸ばす
// Voice
var.insert(String::from("GrandPiano"), SValue::from_i(1)); // @ 音色:GrandPiano
var.insert(String::from("BrightPiano"), SValue::from_i(2)); // @ 音色:BrightPiano
var.insert(String::from("ElectricGrandPiano"), SValue::from_i(3)); // @ 音色:ElectricGrandPiano
Expand Down Expand Up @@ -251,6 +247,6 @@ pub fn init_variables() -> HashMap<String, SValue> {
var.insert(String::from("Castanets"), SValue::from_i(85)); // @ 音色:Castanets
var.insert(String::from("MuteSurdo"), SValue::from_i(86)); // @ 音色:MuteSurdo
var.insert(String::from("OpenSurdo"), SValue::from_i(87)); // @ 音色:OpenSurdo
//</VARIABLES>
//</VARIABLES>
var
}
Loading

0 comments on commit 5f9236e

Please sign in to comment.