3v4l.org

run code in 300+ PHP versions simultaneously
<?php $mt = new music_theory(); var_dump($mt->get_scale_by_name("C")); /************************************************************* * This script is developed by Arturs Sosins aka ar2rsawseen, http://webcodingeasy.com * Fee free to distribute and modify code, but keep reference to its creator * * This class implements music theory for generating scales and chords * based on interval patterns between notes. User can add custom scale and chord pattern. * This class can generate scale notes based on provided scale name and type, * generate chord notes based on provided chord name and type, * transpose scales, transpose chords, * generate all chords that include provided notes, * generate all scales that include provided notes, * * For more information, examples and online documentation visit: * http://webcodingeasy.com/PHP-classes/Implement-music-theory-to-generate-scale-and-chord-notes **************************************************************/ class music_theory { //use sharps or flats private $alt = "sharp"; //array with sharp and flat type notes private $note = array( "sharp" => array("C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"), "flat" => array("C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B") ); //array with scale patterns private $scales = array( "major" => array(2,2,1,2,2,2,1), "ionian" => array(2,2,1,2,2,2,1), "minor" => array(2,1,2,2,1,2,2), "aeolian" => array(2,1,2,2,1,2,2), "dorian" => array(2,1,2,2,2,1,2), "phrygian" => array(1,2,2,2,1,2,2), "lydian" => array(2,2,2,1,2,2,1), "mixolydian" => array(2,2,1,2,2,1,2), "locrian" => array(1,2,2,1,2,2,2), "melodic minor asc" => array(2,1,2,2,2,2,1), "melodic minor desc" => array(2,1,2,2,1,2,2), "chromatic" => array(1,1,1,1,1,1,1,1,1,1,1,1), "pentatonic major" => array(2,2,3,2,3), "whole tone" => array(2,2,2,2,2,2), "pentatonic minor" => array(3,2,2,3,2), "pentatonic blues" => array(3,2,1,1,3), "pentatonic neutral" => array(2,3,2,3,2), "lydian augmented" => array(2,2,2,2,1,2,1), "lydian minor" => array(2,2,2,1,1,2,2), "lydian diminished" => array(2,1,3,1,2,2,1), "major blues" => array(2,1,1,3,2,3), "dominant pentatonic" => array(2,2,3,3,2), "blues" => array(3,2,1,1,3,2) ); private $chords = array( "major" => array(4,3), "minor" => array(3,4), "5" => array(7), "aug" => array(4,4), "dim" => array(3,3), "7" => array(4,3,3), "sus4" => array(5,2), "sus2" => array(2,5), "7sus4" => array(5,2,3), "6" => array(4,3,2), "maj7" => array(4,3,4), "9" => array(4,3,3,4), "add9" => array(4,3,7), "m6" => array(3,4,2), "m7" => array(3,4,3), "mmaj7" => array(3,4,4), "m9" => array(3,4,3,4), "11" => array(4,3,3,4,3), "13" => array(4,3,3,4,3,4), "6add9" => array(4,3,2,5), "-5" => array(4,2), "7-5" => array(4,2,4), "7maj5" => array(4,4,2), "maj9" => array(4,3,4,3) ); private $errors = array(); //return array with all notes public function get_notes(){ return $this->note[$this->alt]; } //use flat notation public function set_flat(){ $this->alt = "flat"; } //use sharp notation public function set_sharp(){ $this->alt = "sharp"; } //return array with all defined scale types public function get_scale_types(){ return array_keys($this->scales); } //return array with all defined chord types public function get_chord_types(){ return array_keys($this->chords); } //return all errors and empty error array public function get_errors(){ $arr = $this->errors; $this->errors = array(); return $arr; } //check if all notes are in array private function is_in($notes, $arr) { $is_in = true; foreach($notes as $note) { if(!in_array(ucfirst(strtolower($note)), $arr)) { $is_in = false; } } return $is_in; } /** * add new scale type with interval pattern * Example input: * $type = "ionian"; //new scale type name * $pattern_array = array(2,2,1,2,2,2,1); //interval pattern **/ public function add_scale_type($type, $pattern_array){ $type = strtolower($type); if(!in_array($type, array_keys($this->scales))) { $this->scales[$type] = $pattern_array; } else { $this->errors[] = "Scale type name already used"; return false; } } /** * add new chord type with interval pattern * Example input: * $type = "major"; //new chord type name * $pattern_array = array(4,3); //interval pattern **/ public function add_chord_type($type, $pattern_array){ $type = strtolower($type); if(!in_array($type, array_keys($this->chords))) { $this->chords[$type] = $pattern_array; } else { $this->errors[] = "Chord type name already used"; return false; } } /** * Get scale notes by name and type (optional transpose) * Example input: * $name = "C"; //scale name * $type = "ionian"; //scale type * $transpose = -1 //intervals to transpose to (default value 0 doesn't transpose), negative number tranposes down, positive - up * Example output: * Array * ( * [0] => B * [1] => C# * [2] => D# * [3] => E * [4] => F# * [5] => G# * [6] => A# * [7] => B * ) **/ public function get_scale_by_name($name, $type, $transpose = 0){ $name = strtolower($name); $name = ucfirst($name); $type = strtolower($type); if(!in_array($name, $this->note['sharp'])) { if(!in_array($name, $this->note['flat'])) { $this->errors[] = "Invalid scale name"; return array(); } else { $notes = $this->note["flat"]; } } else { $notes = $this->note["sharp"]; } if(!in_array($type, array_keys($this->scales))) { $this->errors[] = "Invalid scale type"; return array(); } $scale = array(); $start = array_keys($notes, $name); $note_sum = sizeof($notes)-1; if($start[0] + $transpose < 0) { $current = ($start[0] + $transpose) + $note_sum + 1; } else if($start[0] + $transpose > $note_sum) { $current = (($start[0] + $transpose) - $note_sum) -1; } else { $current = $start[0] + $transpose; } $scale[] = $this->note[$this->alt][$current]; foreach($this->scales[$type] as $num) { $current += $num; if($current > $note_sum) { $current -= ($note_sum + 1); } $scale[] = $this->note[$this->alt][$current]; } return $scale; } /** * Get chord notes by name and type (optional transpose) * Example input: * $name = "C"; //chord name * $type = "major"; //chord type * $transpose = 2 //intervals to transpose to (default value 0 doesn't transpose), negative number tranposes down, positive - up * Example output: * Array * ( * [0] => D * [3] => F# * [5] => A * ) */ public function get_chord_by_name($name, $type, $transpose = 0){ $name = strtolower($name); $name = ucfirst($name); $type = strtolower($type); if(!in_array($name, $this->note['sharp'])) { if(!in_array($name, $this->note['flat'])) { $this->errors[] = "Invalid chord name"; return array(); } else { $notes = $this->note["flat"]; } } else { $notes = $this->note["sharp"]; } if(!in_array($type, array_keys($this->chords))) { $this->errors[] = "Invalid chord type"; return array(); } $chord = array(); $start = array_keys($notes, $name); $note_sum = sizeof($notes)-1; if($start[0] + $transpose < 0) { $current = ($start[0] + $transpose) + $note_sum + 1; } else if($start[0] + $transpose > $note_sum) { $current = (($start[0] + $transpose) - $note_sum) -1; } else { $current = $start[0] + $transpose; } $chord[] = $this->note[$this->alt][$current]; foreach($this->chords[$type] as $num) { $current += $num; if($current > $note_sum) { $current -= ($note_sum + 1); } $chord[] = $this->note[$this->alt][$current]; } return $chord; } /** * Get chord names and types by notes * Example input: * $notes = array("A","F","C", "E"); //notes * Example output: * Array * ( * [0] => Array * ( * [name] => C * [type] => 13 * ) * * [1] => Array * ( * [name] => D * [type] => m9 * ) * ... * ) */ public function get_chords_by_notes($notes){ if(!is_array($notes)) { $notes = array($notes); } $possible = array(); $chords = $this->get_chord_types(); for($i = 0; $i < 12; $i++) { foreach($chords as $chord) { $temp = $this->get_chord_by_name("C", $chord, $i); if($this->is_in($notes, $temp)) { $count = sizeof($possible); $possible[$count]["name"] = current($temp); $possible[$count]["type"] = $chord; } } } return $possible; } /** * Get scale names and types by notes * Example input: * $notes = array("C","D","E","G#","C#"); //notes * Example output: * Array * ( * [0] => Array * ( * [name] => C * [type] => chromatic * ) * * [1] => Array * ( * [name] => C# * [type] => chromatic * ) * ... * ) */ public function get_scales_by_notes($notes){ if(!is_array($notes)) { $notes = array($notes); } $possible = array(); $scales = $this->get_scale_types(); for($i = 0; $i < 12; $i++) { foreach($scales as $scale) { $temp = $this->get_scale_by_name("C", $scale, $i); if($this->is_in($notes, $temp)) { $count = sizeof($possible); $possible[$count]["name"] = current($temp); $possible[$count]["type"] = $scale; } } } return $possible; } /** * Get scale names and types by chord names/types * Provide different chord names with types, * and receive array with all scale names/types which suits provided chords * * Example input: * $chords = array(array("name" => "C", "type" => "major"), array("name" => "A", "type" => "minor")); //chord array * Example output: * Array * ( * [0] => Array * ( * [name] => C * [type] => major * ) * * [1] => Array * ( * [name] => C * [type] => ionian * ) * ... * ) */ public function get_scales_by_chords($chords){ $notes = array(); foreach($chords as $chord) { $chord_notes = $this->get_chord_by_name(ucfirst(strtolower($chord["name"])), $chord["type"]); $notes = array_merge($notes, $chord_notes); } $notes = array_unique($notes); $possible = array(); $scales = $this->get_scale_types(); for($i = 0; $i < 12; $i++) { foreach($scales as $scale) { $temp = $this->get_scale_by_name("C", $scale, $i); if($this->is_in($notes, $temp)) { $count = sizeof($possible); $possible[$count]["name"] = current($temp); $possible[$count]["type"] = $scale; } } } return $possible; } /** * Get chord names and types by scale * Provide scale name and type * and receive all chord names/types which suits provided scale * * Example input: * $scale_name = "C"; //scale name * $scale_type = "ionian" //scale type * Example output: * Array * ( * [0] => Array * ( * [name] => C * [type] => minor * ) * * [1] => Array * ( * [name] => C * [type] => 5 * ) * ... * ) */ public function get_chords_by_scale($scale_name, $scale_type){ $scale_notes = $this->get_scale_by_name(ucfirst(strtolower($scale_name)), strtolower($scale_type)); if(!empty($scale_notes)) { $possible = array(); $chords = $this->get_chord_types(); for($i = 0; $i < 12; $i++) { foreach($chords as $chord) { $temp = $this->get_chord_by_name("C", $chord, $i); if($this->is_in($temp, $scale_notes)) { $count = sizeof($possible); $possible[$count]["name"] = current($temp); $possible[$count]["type"] = $chord; } } } return $possible; } } } ?>

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0080.00816.88
8.3.50.0090.00722.93
8.3.40.0110.00418.92
8.3.30.0090.00619.27
8.3.20.0040.00420.41
8.3.10.0050.00323.56
8.3.00.0000.00819.38
8.2.180.0060.01017.00
8.2.170.0070.01122.96
8.2.160.0140.00020.66
8.2.150.0040.00424.18
8.2.140.0030.00624.66
8.2.130.0080.00026.16
8.2.120.0040.00421.01
8.2.110.0030.00621.14
8.2.100.0040.00817.84
8.2.90.0040.00419.50
8.2.80.0060.00317.97
8.2.70.0060.00317.63
8.2.60.0080.00017.93
8.2.50.0030.00618.07
8.2.40.0030.00518.29
8.2.30.0040.00418.12
8.2.20.0080.00017.72
8.2.10.0040.00418.14
8.2.00.0030.00617.84
8.1.280.0040.01225.92
8.1.270.0080.00023.92
8.1.260.0000.00826.35
8.1.250.0080.00028.09
8.1.240.0100.00317.36
8.1.230.0030.00921.07
8.1.220.0000.00817.79
8.1.210.0040.00719.04
8.1.200.0000.00917.48
8.1.190.0000.00817.35
8.1.180.0030.00518.10
8.1.170.0080.00018.81
8.1.160.0000.00818.86
8.1.150.0040.00419.00
8.1.140.0050.00317.57
8.1.130.0060.00318.02
8.1.120.0000.00717.46
8.1.110.0000.00717.54
8.1.100.0030.00617.59
8.1.90.0040.00417.54
8.1.80.0040.00417.63
8.1.70.0020.00517.55
8.1.60.0060.00317.64
8.1.50.0030.00517.59
8.1.40.0040.00417.61
8.1.30.0050.00317.83
8.1.20.0050.00317.85
8.1.10.0080.00017.75
8.1.00.0080.00017.68
8.0.300.0030.00720.03
8.0.290.0000.01016.75
8.0.280.0000.00718.42
8.0.270.0030.00317.30
8.0.260.0000.00717.36
8.0.250.0000.00717.00
8.0.240.0040.00417.13
8.0.230.0080.00016.97
8.0.220.0050.00317.08
8.0.210.0040.00416.91
8.0.200.0030.00316.98
8.0.190.0030.00617.13
8.0.180.0030.00617.09
8.0.170.0080.00016.98
8.0.160.0040.00417.02
8.0.150.0070.00016.99
8.0.140.0020.00516.94
8.0.130.0060.00013.51
8.0.120.0000.00817.05
8.0.110.0000.00716.95
8.0.100.0000.00817.01
8.0.90.0050.00217.17
8.0.80.0070.01017.05
8.0.70.0030.00616.99
8.0.60.0030.00516.96
8.0.50.0000.00817.00
8.0.30.0050.01517.19
8.0.20.0150.00817.49
8.0.10.0000.00717.04
8.0.00.0050.01216.89
7.4.330.0030.00315.00
7.4.320.0000.00616.74
7.4.300.0030.00316.78
7.4.290.0080.00016.60
7.4.280.0000.01116.57
7.4.270.0030.00516.77
7.4.260.0050.00516.66
7.4.250.0040.00416.64
7.4.240.0010.00716.68
7.4.230.0040.00416.86
7.4.220.0070.01416.77
7.4.210.0080.00816.87
7.4.200.0000.00716.86
7.4.160.0090.01216.65
7.4.150.0160.00317.40
7.4.140.0070.01017.86
7.4.130.0130.00616.75
7.4.120.0070.01116.75
7.4.110.0100.01416.63
7.4.100.0090.00616.72
7.4.90.0090.00916.61
7.4.80.0090.01219.39
7.4.70.0150.00916.66
7.4.60.0120.00616.63
7.4.50.0000.00416.42
7.4.40.0070.01116.71
7.4.30.0100.00716.79
7.4.00.0070.01014.91
7.3.330.0060.00013.31
7.3.320.0050.00313.50
7.3.310.0080.00016.54
7.3.300.0000.00716.57
7.3.290.0030.01316.45
7.3.280.0080.00816.54
7.3.270.0100.00717.40
7.3.260.0070.01116.72
7.3.250.0120.00816.52
7.3.240.0130.00516.77
7.3.230.0140.00316.57
7.3.210.0090.00916.74
7.3.200.0100.01319.39
7.3.190.0070.01716.75
7.3.180.0110.00616.72
7.3.170.0060.01216.66
7.3.160.0080.00816.50
7.2.330.0150.00616.83
7.2.320.0090.01216.82
7.2.310.0100.00716.61
7.2.300.0060.01216.53
7.2.290.0000.01616.70
7.2.60.0090.00616.95
7.2.00.0030.00719.34
7.1.200.0030.00615.62
7.1.100.0000.01317.65
7.1.70.0000.00717.07
7.1.60.0160.01019.40
7.1.50.0030.01016.87
7.1.00.0030.07322.29
7.0.200.0000.01214.76
7.0.140.0070.07021.95
7.0.110.0100.04019.91
7.0.100.0100.04020.01
7.0.90.0170.04020.13
7.0.80.0130.04319.93
7.0.70.0170.04020.14
7.0.60.0070.04719.98
7.0.50.0170.04020.14
7.0.40.0070.04319.64
7.0.30.0170.03319.73
7.0.20.0070.04019.68
7.0.10.0130.04019.70
7.0.00.0030.04719.81
5.6.280.0030.07321.16
5.6.260.0030.04320.70
5.6.250.0100.03020.73
5.6.240.0130.04020.94
5.6.230.0070.04320.74
5.6.220.0030.05020.75
5.6.210.0170.03720.76
5.6.200.0030.05321.03
5.6.190.0030.04321.20
5.6.180.0100.04021.22
5.6.170.0200.02721.26
5.6.160.0030.05021.16
5.6.150.0100.04321.20
5.6.140.0070.03721.04
5.6.130.0100.04020.54
5.6.120.0000.05320.54
5.6.110.0030.05020.54
5.6.100.0130.04020.52
5.6.90.0070.04720.69
5.6.80.0070.03320.16
5.6.70.0030.04720.07
5.6.60.0070.03719.96
5.6.50.0030.03720.14
5.6.40.0030.03320.07
5.6.30.0100.02720.03
5.6.20.0130.03720.00
5.6.10.0130.03020.00
5.6.00.0030.04020.70
5.5.380.0070.04720.43
5.5.370.0100.03720.57
5.5.360.0000.05320.46
5.5.350.0030.04320.53
5.5.340.0130.03721.00
5.5.330.0070.04721.02
5.5.320.0070.04020.95
5.5.310.0070.04721.04
5.5.300.0070.04321.08
5.5.290.0030.03721.09
5.5.280.0000.04720.78
5.5.270.0030.05321.05
5.5.260.0070.04720.75
5.5.250.0000.05320.77
5.5.240.0000.05020.39
5.5.230.0100.03020.32
5.5.220.0030.04720.45
5.5.210.0070.03720.41
5.5.200.0070.03020.11
5.5.190.0000.03720.25
5.5.180.0000.03720.38
5.5.160.0170.03020.11
5.5.150.0130.03720.36
5.5.140.0100.04320.20
5.5.130.0070.04020.34
5.5.120.0070.04320.35
5.5.110.0070.04320.21
5.5.100.0030.03320.06
5.5.90.0070.03020.31
5.5.80.0000.03720.15
5.5.70.0070.04720.31
5.5.60.0030.03720.29
5.5.50.0000.04020.04
5.5.40.0130.03720.18
5.5.30.0070.04320.11
5.5.20.0000.04320.20
5.5.10.0030.04020.07
5.5.00.0030.04020.14
5.4.450.0070.03719.31
5.4.440.0030.04019.50
5.4.430.0000.05019.35
5.4.420.0100.04019.71
5.4.410.0170.02719.24
5.4.400.0100.03719.01
5.4.390.0070.04319.05
5.4.380.0000.04019.20
5.4.370.0000.03719.07
5.4.360.0030.03319.02
5.4.350.0030.03019.22
5.4.340.0070.04019.10
5.4.320.0070.04319.00
5.4.310.0100.03019.23
5.4.300.0030.04319.04
5.4.290.0070.04019.23
5.4.280.0070.04019.04
5.4.270.0070.04019.22
5.4.260.0030.03719.16
5.4.250.0000.03318.98
5.4.240.0030.04319.06
5.4.230.0070.04319.04
5.4.220.0030.04719.01
5.4.210.0070.04319.30
5.4.200.0070.03319.04
5.4.190.0000.04019.02
5.4.180.0000.04719.25
5.4.170.0100.03319.03
5.4.160.0030.04719.14
5.4.150.0000.05019.00
5.4.140.0070.04316.54
5.4.130.0030.04016.36
5.4.120.0000.04016.51
5.4.110.0030.04316.52
5.4.100.0000.04316.45
5.4.90.0000.04316.58
5.4.80.0100.03316.59
5.4.70.0000.04716.59
5.4.60.0030.03716.61
5.4.50.0030.04316.57
5.4.40.0030.04016.53
5.4.30.0100.03016.69
5.4.20.0030.04316.59
5.4.10.0130.03716.59
5.4.00.0000.03715.84

preferences:
102.21 ms | 401 KiB | 5 Q