[ocmml/slmml] * implemented Ring Modulator and Sync
| @@ -55,6 +55,7 @@ | ||
| 55 | 55 | #region 定数の定義 |
| 56 | 56 | protected const int MULTIPLY = 32; |
| 57 | 57 | protected const int MAX_PIPE = 3; |
| 58 | + protected const int MAX_SYNC_SOURCE = 3; | |
| 58 | 59 | #endregion |
| 59 | 60 | |
| 60 | 61 | #region 非公開メソッドの定義 |
| @@ -132,6 +133,7 @@ | ||
| 132 | 133 | m_sequencer.AddTrack(track); |
| 133 | 134 | } |
| 134 | 135 | m_sequencer.CreatePipes(m_maxPipe + 1); |
| 136 | + m_sequencer.CreateSyncSources(m_maxSyncSource + 1); | |
| 135 | 137 | return m_sequencer; |
| 136 | 138 | } |
| 137 | 139 |
| @@ -275,6 +277,8 @@ | ||
| 275 | 277 | int decay = 64; |
| 276 | 278 | int sustain = 32; |
| 277 | 279 | int release = 0; |
| 280 | + int sens = 0; | |
| 281 | + int mode = 0; | |
| 278 | 282 | switch (c) |
| 279 | 283 | { |
| 280 | 284 | case 'v': |
| @@ -437,7 +441,7 @@ | ||
| 437 | 441 | break; |
| 438 | 442 | case 'i': |
| 439 | 443 | NextToken(); |
| 440 | - int sens = (int)UIntToken(0); | |
| 444 | + sens = (int)UIntToken(0); | |
| 441 | 445 | if (CharacterToken() == ',') |
| 442 | 446 | { |
| 443 | 447 | NextToken(); |
| @@ -448,7 +452,7 @@ | ||
| 448 | 452 | break; |
| 449 | 453 | case 'o': |
| 450 | 454 | NextToken(); |
| 451 | - int mode = (int)UIntToken(0); | |
| 455 | + mode = (int)UIntToken(0); | |
| 452 | 456 | if (CharacterToken() == ',') |
| 453 | 457 | { |
| 454 | 458 | NextToken(); |
| @@ -462,6 +466,41 @@ | ||
| 462 | 466 | } |
| 463 | 467 | m_tracks[m_trackIndex].RecordOutput((ChannelOutputMode)mode, attack); |
| 464 | 468 | break; |
| 469 | + case 'r': | |
| 470 | + NextToken(); | |
| 471 | + sens = (int)UIntToken(0); | |
| 472 | + if (CharacterToken() == ',') | |
| 473 | + { | |
| 474 | + NextToken(); | |
| 475 | + attack = (int)UIntToken((uint)attack); | |
| 476 | + attack = Math.Min(attack, m_maxPipe); | |
| 477 | + } | |
| 478 | + m_tracks[m_trackIndex].RecordRing(sens, attack); | |
| 479 | + break; | |
| 480 | + case 's': | |
| 481 | + NextToken(); | |
| 482 | + mode = (int)UIntToken(0); | |
| 483 | + if (CharacterToken() == ',') | |
| 484 | + { | |
| 485 | + NextToken(); | |
| 486 | + attack = (int)UIntToken((uint)attack); | |
| 487 | + if (mode == 1) | |
| 488 | + { | |
| 489 | + if (attack > m_maxSyncSource) | |
| 490 | + { | |
| 491 | + m_maxSyncSource = attack; | |
| 492 | + if (m_maxSyncSource >= MAX_SYNC_SOURCE) | |
| 493 | + m_maxSyncSource = attack = MAX_SYNC_SOURCE; | |
| 494 | + } | |
| 495 | + } | |
| 496 | + else if (mode == 2) | |
| 497 | + { | |
| 498 | + if (attack > m_maxSyncSource) | |
| 499 | + attack = m_maxSyncSource; | |
| 500 | + } | |
| 501 | + } | |
| 502 | + m_tracks[m_trackIndex].RecordSync((ChannelOutputMode)mode, attack); | |
| 503 | + break; | |
| 465 | 504 | default: |
| 466 | 505 | m_form = (OscillatorForm)UIntToken((uint)m_form); |
| 467 | 506 | subform = 0; |
| @@ -689,6 +728,7 @@ | ||
| 689 | 728 | private int m_maxGate; |
| 690 | 729 | private int m_noteShift; |
| 691 | 730 | private int m_maxPipe; |
| 731 | + private int m_maxSyncSource; | |
| 692 | 732 | #endregion |
| 693 | 733 | } |
| 694 | 734 | } |
| @@ -96,6 +96,28 @@ | ||
| 96 | 96 | for (int i = start; i < end; i++) |
| 97 | 97 | samples[i] = NextSample; |
| 98 | 98 | } |
| 99 | + | |
| 100 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 101 | + { | |
| 102 | + for (int i = start; i < end; i++) | |
| 103 | + { | |
| 104 | + if (syncIn[i]) | |
| 105 | + ResetPhase(); | |
| 106 | + samples[i] = s_table[WaveIndex, (m_phase >> PHASE_SHIFT) + 11]; | |
| 107 | + AddPhase(1); | |
| 108 | + } | |
| 109 | + } | |
| 110 | + | |
| 111 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 112 | + { | |
| 113 | + for (int i = start; i < end; i++) | |
| 114 | + { | |
| 115 | + samples[i] = s_table[WaveIndex, (m_phase >> PHASE_SHIFT) + 11]; | |
| 116 | + m_phase += m_frequencyShift; | |
| 117 | + syncOut[i] = m_phase > PHASE_MASK; | |
| 118 | + m_phase &= PHASE_MASK; | |
| 119 | + } | |
| 120 | + } | |
| 99 | 121 | #endregion |
| 100 | 122 | |
| 101 | 123 | #region 公開プロパティの定義 |
| @@ -135,6 +135,16 @@ | ||
| 135 | 135 | samples[i] = NextSample; |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 139 | + { | |
| 140 | + GetSamples(ref samples, start, end); | |
| 141 | + } | |
| 142 | + | |
| 143 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 144 | + { | |
| 145 | + GetSamples(ref samples, start, end); | |
| 146 | + } | |
| 147 | + | |
| 138 | 148 | public double NextSampleFrom(int offset) |
| 139 | 149 | { |
| 140 | 150 | double value = (m_wave - 64) / 64.0; |
| @@ -78,6 +78,16 @@ | ||
| 78 | 78 | samples[i] = NextSample; |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 82 | + { | |
| 83 | + GetSamples(ref samples, start, end); | |
| 84 | + } | |
| 85 | + | |
| 86 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 87 | + { | |
| 88 | + GetSamples(ref samples, start, end); | |
| 89 | + } | |
| 90 | + | |
| 81 | 91 | public new void ResetPhase() |
| 82 | 92 | { |
| 83 | 93 | if (ShouldResetPhase) |
| @@ -71,6 +71,28 @@ | ||
| 71 | 71 | samples[i] = NextSample; |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 75 | + { | |
| 76 | + for (int i = start; i < end; i++) | |
| 77 | + { | |
| 78 | + if (syncIn[i]) | |
| 79 | + ResetPhase(); | |
| 80 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 81 | + AddPhase(1); | |
| 82 | + } | |
| 83 | + } | |
| 84 | + | |
| 85 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 86 | + { | |
| 87 | + for (int i = start; i < end; i++) | |
| 88 | + { | |
| 89 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 90 | + m_phase += m_frequencyShift; | |
| 91 | + syncOut[i] = m_phase > PHASE_MASK; | |
| 92 | + m_phase &= PHASE_MASK; | |
| 93 | + } | |
| 94 | + } | |
| 95 | + | |
| 74 | 96 | public double NextSample |
| 75 | 97 | { |
| 76 | 98 | get |
| @@ -71,6 +71,28 @@ | ||
| 71 | 71 | for (int i = start; i < end; i++) |
| 72 | 72 | samples[i] = NextSample; |
| 73 | 73 | } |
| 74 | + | |
| 75 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 76 | + { | |
| 77 | + for (int i = start; i < end; i++) | |
| 78 | + { | |
| 79 | + if (syncIn[i]) | |
| 80 | + ResetPhase(); | |
| 81 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 82 | + AddPhase(1); | |
| 83 | + } | |
| 84 | + } | |
| 85 | + | |
| 86 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 87 | + { | |
| 88 | + for (int i = start; i < end; i++) | |
| 89 | + { | |
| 90 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 91 | + m_phase += m_frequencyShift; | |
| 92 | + syncOut[i] = m_phase > PHASE_MASK; | |
| 93 | + m_phase &= PHASE_MASK; | |
| 94 | + } | |
| 95 | + } | |
| 74 | 96 | #endregion |
| 75 | 97 | |
| 76 | 98 | #region 公開プロパティの定義 |
| @@ -37,6 +37,8 @@ | ||
| 37 | 37 | void AddPhase(int time); |
| 38 | 38 | void ResetPhase(); |
| 39 | 39 | void GetSamples(ref double[] samples, int start, int end); |
| 40 | + void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end); | |
| 41 | + void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end); | |
| 40 | 42 | double NextSampleFrom(int offset); |
| 41 | 43 | #endregion |
| 42 | 44 |
| @@ -69,6 +69,28 @@ | ||
| 69 | 69 | for (int i = start; i < end; i++) |
| 70 | 70 | samples[i] = NextSample; |
| 71 | 71 | } |
| 72 | + | |
| 73 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 74 | + { | |
| 75 | + for (int i = start; i < end; i++) | |
| 76 | + { | |
| 77 | + if (syncIn[i]) | |
| 78 | + ResetPhase(); | |
| 79 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 80 | + AddPhase(1); | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 85 | + { | |
| 86 | + for (int i = start; i < end; i++) | |
| 87 | + { | |
| 88 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 89 | + m_phase += m_frequencyShift; | |
| 90 | + syncOut[i] = m_phase > PHASE_MASK; | |
| 91 | + m_phase &= PHASE_MASK; | |
| 92 | + } | |
| 93 | + } | |
| 72 | 94 | #endregion |
| 73 | 95 | |
| 74 | 96 | #region 公開プロパティの定義 |
| @@ -74,6 +74,16 @@ | ||
| 74 | 74 | samples[i] = NextSample; |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 78 | + { | |
| 79 | + GetSamples(ref samples, start, end); | |
| 80 | + } | |
| 81 | + | |
| 82 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 83 | + { | |
| 84 | + GetSamples(ref samples, start, end); | |
| 85 | + } | |
| 86 | + | |
| 77 | 87 | public new void AddPhase(int time) |
| 78 | 88 | { |
| 79 | 89 | m_phase = m_phase + FC_NOISE_PHASE_DELTA * time; |
| @@ -81,6 +81,16 @@ | ||
| 81 | 81 | for (int i = start; i < end; i++) |
| 82 | 82 | samples[i] = NextSample; |
| 83 | 83 | } |
| 84 | + | |
| 85 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 86 | + { | |
| 87 | + GetSamples(ref samples, start, end); | |
| 88 | + } | |
| 89 | + | |
| 90 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 91 | + { | |
| 92 | + GetSamples(ref samples, start, end); | |
| 93 | + } | |
| 84 | 94 | #endregion |
| 85 | 95 | |
| 86 | 96 | #region 非公開メソッドの定義 |
| @@ -81,6 +81,16 @@ | ||
| 81 | 81 | for (int i = start; i < end; i++) |
| 82 | 82 | samples[i] = NextSample; |
| 83 | 83 | } |
| 84 | + | |
| 85 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 86 | + { | |
| 87 | + GetSamples(ref samples, start, end); | |
| 88 | + } | |
| 89 | + | |
| 90 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 91 | + { | |
| 92 | + GetSamples(ref samples, start, end); | |
| 93 | + } | |
| 84 | 94 | #endregion |
| 85 | 95 | |
| 86 | 96 | #region 非公開メソッドの定義 |
| @@ -53,6 +53,28 @@ | ||
| 53 | 53 | for (int i = start; i < end; i++) |
| 54 | 54 | samples[i] = NextSample; |
| 55 | 55 | } |
| 56 | + | |
| 57 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 58 | + { | |
| 59 | + for (int i = start; i < end; i++) | |
| 60 | + { | |
| 61 | + if (syncIn[i]) | |
| 62 | + ResetPhase(); | |
| 63 | + samples[i] = m_phase < m_pwm ? 1.0 : -1.0; | |
| 64 | + AddPhase(1); | |
| 65 | + } | |
| 66 | + } | |
| 67 | + | |
| 68 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 69 | + { | |
| 70 | + for (int i = start; i < end; i++) | |
| 71 | + { | |
| 72 | + samples[i] = m_phase < m_pwm ? 1.0 : -1.0; | |
| 73 | + m_phase += m_frequencyShift; | |
| 74 | + syncOut[i] = m_phase > PHASE_MASK; | |
| 75 | + m_phase &= PHASE_MASK; | |
| 76 | + } | |
| 77 | + } | |
| 56 | 78 | #endregion |
| 57 | 79 | |
| 58 | 80 | #region 公開プロパティの定義 |
| @@ -69,6 +69,28 @@ | ||
| 69 | 69 | for (int i = start; i < end; i++) |
| 70 | 70 | samples[i] = NextSample; |
| 71 | 71 | } |
| 72 | + | |
| 73 | + public void GetSamplesSyncIn(ref double[] samples, bool[] syncIn, int start, int end) | |
| 74 | + { | |
| 75 | + for (int i = start; i < end; i++) | |
| 76 | + { | |
| 77 | + if (syncIn[i]) | |
| 78 | + ResetPhase(); | |
| 79 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 80 | + AddPhase(1); | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + public void GetSamplesSyncOut(ref double[] samples, ref bool[] syncOut, int start, int end) | |
| 85 | + { | |
| 86 | + for (int i = start; i < end; i++) | |
| 87 | + { | |
| 88 | + samples[i] = s_table[m_phase >> PHASE_SHIFT]; | |
| 89 | + m_phase += m_frequencyShift; | |
| 90 | + syncOut[i] = m_phase > PHASE_MASK; | |
| 91 | + m_phase &= PHASE_MASK; | |
| 92 | + } | |
| 93 | + } | |
| 72 | 94 | #endregion |
| 73 | 95 | |
| 74 | 96 | #region 公開プロパティの定義 |
| @@ -171,6 +171,15 @@ | ||
| 171 | 171 | { |
| 172 | 172 | Channel.CreatePipes(number); |
| 173 | 173 | } |
| 174 | + | |
| 175 | + /// <summary> | |
| 176 | + /// チャンネルオブジェクトに同期ソース生成を行います | |
| 177 | + /// </summary> | |
| 178 | + /// <param name="number">パイプ数</param> | |
| 179 | + public void CreateSyncSources(int number) | |
| 180 | + { | |
| 181 | + Channel.CreateSyncSources(number); | |
| 182 | + } | |
| 174 | 183 | #endregion |
| 175 | 184 | |
| 176 | 185 | #region 非公開メソッドの定義 |
| @@ -0,0 +1,48 @@ | ||
| 1 | +/* | |
| 2 | + Copyright (c) 2009, hkrn All rights reserved. | |
| 3 | + | |
| 4 | + Redistribution and use in source and binary forms, with or without | |
| 5 | + modification, are permitted provided that the following conditions are met: | |
| 6 | + | |
| 7 | + Redistributions of source code must retain the above copyright notice, this | |
| 8 | + list of conditions and the following disclaimer. Redistributions in binary | |
| 9 | + form must reproduce the above copyright notice, this list of conditions and | |
| 10 | + the following disclaimer in the documentation and/or other materials | |
| 11 | + provided with the distribution. Neither the name of the hkrn nor | |
| 12 | + the names of its contributors may be used to endorse or promote products | |
| 13 | + derived from this software without specific prior written permission. | |
| 14 | + | |
| 15 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| 16 | + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 17 | + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 18 | + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | |
| 19 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 20 | + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 21 | + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| 22 | + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 23 | + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 24 | + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |
| 25 | + DAMAGE. | |
| 26 | + */ | |
| 27 | + | |
| 28 | +// | |
| 29 | +// $Id: Output.cs 58 2009-04-04 12:56:58Z hikarin $ | |
| 30 | +// | |
| 31 | + | |
| 32 | +namespace SlMML.Events | |
| 33 | +{ | |
| 34 | + public sealed class Sync : Event | |
| 35 | + { | |
| 36 | + public ChannelOutputMode Mode | |
| 37 | + { | |
| 38 | + get; | |
| 39 | + set; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public int Pipe | |
| 43 | + { | |
| 44 | + get; | |
| 45 | + set; | |
| 46 | + } | |
| 47 | + } | |
| 48 | +} |
| @@ -0,0 +1,48 @@ | ||
| 1 | +/* | |
| 2 | + Copyright (c) 2009, hkrn All rights reserved. | |
| 3 | + | |
| 4 | + Redistribution and use in source and binary forms, with or without | |
| 5 | + modification, are permitted provided that the following conditions are met: | |
| 6 | + | |
| 7 | + Redistributions of source code must retain the above copyright notice, this | |
| 8 | + list of conditions and the following disclaimer. Redistributions in binary | |
| 9 | + form must reproduce the above copyright notice, this list of conditions and | |
| 10 | + the following disclaimer in the documentation and/or other materials | |
| 11 | + provided with the distribution. Neither the name of the hkrn nor | |
| 12 | + the names of its contributors may be used to endorse or promote products | |
| 13 | + derived from this software without specific prior written permission. | |
| 14 | + | |
| 15 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| 16 | + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 17 | + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 18 | + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | |
| 19 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 20 | + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 21 | + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| 22 | + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 23 | + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 24 | + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |
| 25 | + DAMAGE. | |
| 26 | + */ | |
| 27 | + | |
| 28 | +// | |
| 29 | +// $Id: Input.cs 58 2009-04-04 12:56:58Z hikarin $ | |
| 30 | +// | |
| 31 | + | |
| 32 | +namespace SlMML.Events | |
| 33 | +{ | |
| 34 | + public sealed class Ring : Event | |
| 35 | + { | |
| 36 | + public int Sens | |
| 37 | + { | |
| 38 | + get; | |
| 39 | + set; | |
| 40 | + } | |
| 41 | + | |
| 42 | + public int Pipe | |
| 43 | + { | |
| 44 | + get; | |
| 45 | + set; | |
| 46 | + } | |
| 47 | + } | |
| 48 | +} |
| @@ -131,6 +131,10 @@ | ||
| 131 | 131 | m_channel.Output = (Events.Output)e; |
| 132 | 132 | else if (e is Events.Expression) |
| 133 | 133 | m_channel.Expression = ((Events.Expression)e).Value; |
| 134 | + else if (e is Events.Ring) | |
| 135 | + m_channel.Ring = (Events.Ring)e; | |
| 136 | + else if (e is Events.Sync) | |
| 137 | + m_channel.Sync = (Events.Sync)e; | |
| 134 | 138 | else if (e is Events.Close) |
| 135 | 139 | m_channel.Close(); |
| 136 | 140 | else if (e is Events.Eot) |
| @@ -401,6 +405,31 @@ | ||
| 401 | 405 | SetDeltaAndAddEvent(e); |
| 402 | 406 | } |
| 403 | 407 | |
| 408 | + /// <summary> | |
| 409 | + /// リングを記録します | |
| 410 | + /// </summary> | |
| 411 | + /// <param name="inSens"></param> | |
| 412 | + /// <param name="pipe"></param> | |
| 413 | + public void RecordRing(int inSens, int pipe) | |
| 414 | + { | |
| 415 | + Events.Ring e = new Events.Ring() { Sens = inSens, Pipe = pipe }; | |
| 416 | + SetDeltaAndAddEvent(e); | |
| 417 | + } | |
| 418 | + | |
| 419 | + /// <summary> | |
| 420 | + /// 同期を記録します | |
| 421 | + /// </summary> | |
| 422 | + /// <param name="mode"></param> | |
| 423 | + /// <param name="pipe"></param> | |
| 424 | + public void RecordSync(ChannelOutputMode mode, int pipe) | |
| 425 | + { | |
| 426 | + Events.Sync e = new Events.Sync() { Mode = mode, Pipe = pipe }; | |
| 427 | + SetDeltaAndAddEvent(e); | |
| 428 | + } | |
| 429 | + | |
| 430 | + /// <summary> | |
| 431 | + /// 終了マークを記録します | |
| 432 | + /// </summary> | |
| 404 | 433 | public void RecordClose() |
| 405 | 434 | { |
| 406 | 435 | Events.Close e = new Events.Close(); |
| @@ -632,6 +661,18 @@ | ||
| 632 | 661 | } |
| 633 | 662 | else if (e is Events.Expression) |
| 634 | 663 | data["expression"] = ((Events.Expression)e).Value.ToString(); |
| 664 | + else if (e is Events.Ring) | |
| 665 | + { | |
| 666 | + Events.Ring ring = (Events.Ring)e; | |
| 667 | + data["sens"] = ring.Sens.ToString(); | |
| 668 | + data["pipe"] = ring.Pipe.ToString(); | |
| 669 | + } | |
| 670 | + else if (e is Events.Output) | |
| 671 | + { | |
| 672 | + Events.Sync sync = (Events.Sync)e; | |
| 673 | + data["mode"] = ((int)sync.Mode).ToString(); | |
| 674 | + data["pipe"] = sync.Pipe.ToString(); | |
| 675 | + } | |
| 635 | 676 | r.Add(data); |
| 636 | 677 | } |
| 637 | 678 | return r; |
| @@ -87,6 +87,18 @@ | ||
| 87 | 87 | } |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | + public static void CreateSyncSources(int number) | |
| 91 | + { | |
| 92 | + s_syncSource = new bool[number][]; | |
| 93 | + s_syncSourceLength = number; | |
| 94 | + for (int i = 0; i < number; i++) | |
| 95 | + { | |
| 96 | + s_syncSource[i] = new bool[s_sampleLength]; | |
| 97 | + for (int j = 0; j < s_sampleLength; j++) | |
| 98 | + s_syncSource[i][j] = false; | |
| 99 | + } | |
| 100 | + } | |
| 101 | + | |
| 90 | 102 | public static double FrequencyFromIndex(int index) |
| 91 | 103 | { |
| 92 | 104 | index = Math.Min(Math.Max(index, 0), Math.Max(s_frequencyLength, 1) - 1); |
| @@ -124,6 +136,8 @@ | ||
| 124 | 136 | Velocity = 100; |
| 125 | 137 | Input = new Events.Input() { Sens = 0, Pipe = 0 }; |
| 126 | 138 | Output = new Events.Output() { Mode = ChannelOutputMode.Default, Pipe = 0 }; |
| 139 | + Ring = new Events.Ring() { Sens = 0, Pipe = 0 }; | |
| 140 | + Sync = new Events.Sync() { Mode = ChannelOutputMode.Default, Pipe = 0 }; | |
| 127 | 141 | } |
| 128 | 142 | #endregion |
| 129 | 143 |
| @@ -198,7 +212,18 @@ | ||
| 198 | 212 | { |
| 199 | 213 | if (!m_osc2connect) |
| 200 | 214 | { |
| 201 | - m_mod1.GetSamples(ref s_samples, start, end); | |
| 215 | + switch (m_syncMode) | |
| 216 | + { | |
| 217 | + case ChannelOutputMode.Overwrite: | |
| 218 | + m_mod1.GetSamplesSyncOut(ref s_samples, ref s_syncSource[m_syncPipe], start, end); | |
| 219 | + break; | |
| 220 | + case ChannelOutputMode.Add: | |
| 221 | + m_mod1.GetSamplesSyncIn(ref s_samples, s_syncSource[m_syncPipe], start, end); | |
| 222 | + break; | |
| 223 | + default: | |
| 224 | + m_mod1.GetSamples(ref s_samples, start, end); | |
| 225 | + break; | |
| 226 | + } | |
| 202 | 227 | if (VolumeMode == 0) |
| 203 | 228 | m_vco.GetAmplitudeSamplesLinear(ref s_samples, start, end, m_ampLevel); |
| 204 | 229 | else |
| @@ -218,7 +243,18 @@ | ||
| 218 | 243 | m_mod2.AddPhase(e - s - 1); |
| 219 | 244 | } |
| 220 | 245 | m_mod1.Frequency = Channel.FrequencyFromIndex(frequencyIndex); |
| 221 | - m_mod1.GetSamples(ref s_samples, s, e); | |
| 246 | + switch (m_syncMode) | |
| 247 | + { | |
| 248 | + case ChannelOutputMode.Overwrite: | |
| 249 | + m_mod1.GetSamplesSyncOut(ref s_samples, ref s_syncSource[m_syncPipe], s, e); | |
| 250 | + break; | |
| 251 | + case ChannelOutputMode.Add: | |
| 252 | + m_mod1.GetSamplesSyncIn(ref s_samples, s_syncSource[m_syncPipe], s, e); | |
| 253 | + break; | |
| 254 | + default: | |
| 255 | + m_mod1.GetSamples(ref s_samples, s, e); | |
| 256 | + break; | |
| 257 | + } | |
| 222 | 258 | if (VolumeMode == 0) |
| 223 | 259 | m_vco.GetAmplitudeSamplesLinear(ref s_samples, s, e, m_ampLevel); |
| 224 | 260 | else |
| @@ -258,6 +294,11 @@ | ||
| 258 | 294 | m_vco.GetAmplitudeSamplesNonLinear(ref s_samples, start, end, m_ampLevel); |
| 259 | 295 | } |
| 260 | 296 | } |
| 297 | + if (m_ringSens >= 0.000001) | |
| 298 | + { | |
| 299 | + for (int i = start; i < end; i++) | |
| 300 | + s_samples[i] *= s_pipeArray[m_ringPipe][i] * m_ringSens; | |
| 301 | + } | |
| 261 | 302 | double key = m_mod1.Frequency; |
| 262 | 303 | m_formant.GetSamples(ref s_samples, start, end); |
| 263 | 304 | m_filter.Envelope = m_vcf; |
| @@ -369,7 +410,7 @@ | ||
| 369 | 410 | set |
| 370 | 411 | { |
| 371 | 412 | m_inSens = (1 << (value.Sens - 1)) * (1.0 / 8.0) * Modulator.PHASE_LENGTH; |
| 372 | - m_inPipe = value.Pipe; | |
| 413 | + m_inPipe = Math.Min(Math.Max(value.Pipe, 0), s_pipeArrayNum); | |
| 373 | 414 | } |
| 374 | 415 | } |
| 375 | 416 |
| @@ -382,7 +423,6 @@ | ||
| 382 | 423 | } |
| 383 | 424 | } |
| 384 | 425 | |
| 385 | - | |
| 386 | 426 | public int NoteIndex |
| 387 | 427 | { |
| 388 | 428 | set |
| @@ -470,6 +510,24 @@ | ||
| 470 | 510 | m_ampLevel = m_velocity * m_expression; |
| 471 | 511 | } |
| 472 | 512 | } |
| 513 | + | |
| 514 | + public Events.Ring Ring | |
| 515 | + { | |
| 516 | + set | |
| 517 | + { | |
| 518 | + m_ringSens = (1 << (value.Sens - 1)) / 8.0; | |
| 519 | + m_ringPipe = Math.Min(Math.Max(value.Pipe, 0), s_pipeArrayNum); | |
| 520 | + } | |
| 521 | + } | |
| 522 | + | |
| 523 | + public Events.Sync Sync | |
| 524 | + { | |
| 525 | + set | |
| 526 | + { | |
| 527 | + m_syncMode = value.Mode; | |
| 528 | + m_syncPipe = Math.Min(Math.Max(value.Pipe, 0), s_pipeArrayNum); | |
| 529 | + } | |
| 530 | + } | |
| 473 | 531 | #endregion |
| 474 | 532 | |
| 475 | 533 | #region メンバー変数の定義 |
| @@ -478,9 +536,11 @@ | ||
| 478 | 536 | private static int s_frequencyLength = 0; |
| 479 | 537 | private static double[] s_volumeMap = new double[VELOCITY_MAX]; |
| 480 | 538 | private static int s_volumeLength = 0; |
| 481 | - private static double[] s_samples; | |
| 539 | + private static double[] s_samples = null; | |
| 482 | 540 | private static int s_sampleLength = 0; |
| 483 | - private static double[][] s_pipeArray; | |
| 541 | + private static double[][] s_pipeArray = null; | |
| 542 | + private static int s_syncSourceLength = 0; | |
| 543 | + private static bool[][] s_syncSource; | |
| 484 | 544 | private static int s_pipeArrayNum = 0; |
| 485 | 545 | private static int s_lfoDelta = VELOCITY_MAX; |
| 486 | 546 | private Envelope m_vco; |
| @@ -514,6 +574,10 @@ | ||
| 514 | 574 | private int m_inPipe; |
| 515 | 575 | private ChannelOutputMode m_outMode; |
| 516 | 576 | private int m_outPipe; |
| 577 | + private double m_ringSens; | |
| 578 | + private int m_ringPipe; | |
| 579 | + private ChannelOutputMode m_syncMode; | |
| 580 | + private int m_syncPipe; | |
| 517 | 581 | #endregion |
| 518 | 582 | } |
| 519 | 583 | } |