f@0
|
1 /*
|
f@0
|
2 Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation.
|
f@0
|
3
|
f@0
|
4 Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)
|
f@0
|
5
|
f@0
|
6 This program is free software: you can redistribute it and/or modify
|
f@0
|
7 it under the terms of the GNU General Public License as published by
|
f@0
|
8 the Free Software Foundation, either version 3 of the License, or
|
f@0
|
9 (at your option) any later version.
|
f@0
|
10
|
f@0
|
11 This program is distributed in the hope that it will be useful,
|
f@0
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
f@0
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
f@0
|
14 GNU General Public License for more details.
|
f@0
|
15
|
f@0
|
16 You should have received a copy of the GNU General Public License
|
f@0
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
f@0
|
18 */
|
f@0
|
19 package uk.ac.qmul.eecs.depic.daw.referencesound;
|
f@0
|
20
|
f@0
|
21 import net.beadsproject.beads.core.AudioContext;
|
f@0
|
22 import net.beadsproject.beads.core.Bead;
|
f@0
|
23 import net.beadsproject.beads.core.UGen;
|
f@0
|
24 import net.beadsproject.beads.data.Buffer;
|
f@0
|
25 import net.beadsproject.beads.ugens.Envelope;
|
f@0
|
26 import net.beadsproject.beads.ugens.Gain;
|
f@0
|
27 import net.beadsproject.beads.ugens.WavePlayer;
|
f@0
|
28 import uk.ac.qmul.eecs.depic.patterns.Range;
|
f@0
|
29 import uk.ac.qmul.eecs.depic.patterns.Sequence;
|
f@0
|
30
|
f@0
|
31 /**
|
f@0
|
32 * Implements a sequence mapping using beads engine and simple wave tables ugens
|
f@0
|
33 *
|
f@0
|
34 *
|
f@0
|
35 */
|
f@0
|
36 class BeadsWaveTableSequenceMapping extends BeadsSequenceMapping {
|
f@0
|
37 private Range<Float> renderCurvePitchSpan;
|
f@0
|
38 private Range<Float> renderValuePitchSpan;
|
f@0
|
39 private static final float ATTACK_TIME_MS = 5.0f;
|
f@0
|
40
|
f@0
|
41 static {
|
f@0
|
42 /* loads the buffer for the PeakLevelPitchedUgen and stores it into staticBuffs */
|
f@0
|
43 int bufferLen = 4096;
|
f@0
|
44 Buffer pulse = new Buffer(bufferLen);
|
f@0
|
45 int pulseWidth = bufferLen/10;
|
f@0
|
46
|
f@0
|
47 for(int i=0; i<pulseWidth;i++){
|
f@0
|
48 pulse.buf[i] = 1.0f;
|
f@0
|
49 }
|
f@0
|
50
|
f@0
|
51 for(int i=pulseWidth; i<bufferLen; i++){
|
f@0
|
52 pulse.buf[i] = -1.0f;
|
f@0
|
53 }
|
f@0
|
54
|
f@0
|
55 Buffer.staticBufs.put("Pulse", pulse);
|
f@0
|
56 }
|
f@0
|
57
|
f@0
|
58 public BeadsWaveTableSequenceMapping(AudioContext ac, Range<Float> curvePitchSpan, Range<Float> valuePitchSpan){
|
f@0
|
59 super(ac);
|
f@0
|
60 renderCurvePitchSpan = curvePitchSpan;
|
f@0
|
61 renderValuePitchSpan = valuePitchSpan;
|
f@0
|
62 }
|
f@0
|
63
|
f@0
|
64 @Override
|
f@0
|
65 protected PitchedUGen createRenderValueUGen(){
|
f@0
|
66 return new BufferPitchedUGen(ac, renderValuePitchSpan, Buffer.SINE);
|
f@0
|
67 }
|
f@0
|
68
|
f@0
|
69 @Override
|
f@0
|
70 protected PitchedUGen createRenderCurveUGen(){
|
f@0
|
71 return new BufferPitchedUGen(ac, renderCurvePitchSpan, Buffer.SINE);
|
f@0
|
72 }
|
f@0
|
73
|
f@0
|
74
|
f@0
|
75 @Override
|
f@0
|
76 protected Range<Float> getRenderValuePitchSpan() {
|
f@0
|
77 return renderValuePitchSpan;
|
f@0
|
78 }
|
f@0
|
79
|
f@0
|
80 @Override
|
f@0
|
81 protected Range<Float> getRenderCurvePitchSpan() {
|
f@0
|
82 return renderCurvePitchSpan;
|
f@0
|
83 }
|
f@0
|
84
|
f@0
|
85 private class BufferPitchedUGen extends PitchedUGen {
|
f@0
|
86 private Gain gain;
|
f@0
|
87 private WavePlayer player;
|
f@0
|
88 private float maxFreq;
|
f@0
|
89 private float minFreq;
|
f@0
|
90 private Envelope env;
|
f@0
|
91
|
f@0
|
92 /**
|
f@0
|
93 *
|
f@0
|
94 * Pulse TriangularBuffer Square Saw Noise Sine
|
f@0
|
95 *
|
f@0
|
96 * @param ac
|
f@0
|
97 * @param pitchSpan
|
f@0
|
98 * @param buffer
|
f@0
|
99 */
|
f@0
|
100 public BufferPitchedUGen(AudioContext ac, Range<Float> pitchSpan, Buffer buffer) {
|
f@0
|
101 super(ac);
|
f@0
|
102 if(maxFreq < minFreq){
|
f@0
|
103 throw new IllegalArgumentException("minFreq must be lower than maxFreq. minFreq: "+minFreq+" maxFreq:"+maxFreq );
|
f@0
|
104 }
|
f@0
|
105
|
f@0
|
106 this.minFreq = pitchSpan.getStart();
|
f@0
|
107 this.maxFreq = pitchSpan.getEnd();
|
f@0
|
108 gain = new Gain(ac, 1, 0.5f);
|
f@0
|
109 player = new WavePlayer(ac,minFreq,buffer);
|
f@0
|
110
|
f@0
|
111 gain.addInput(player);
|
f@0
|
112
|
f@0
|
113 addToChainOutput(gain);
|
f@0
|
114 }
|
f@0
|
115
|
f@0
|
116 @Override
|
f@0
|
117 public void setPitch(float pitch){
|
f@0
|
118 /* set the frequency for both the actual curve sound and the threshold sound */
|
f@0
|
119 player.setFrequency(pitch);
|
f@0
|
120
|
f@0
|
121 }
|
f@0
|
122
|
f@0
|
123 @Override
|
f@0
|
124 public void setPitch(UGen pitch) {
|
f@0
|
125 player.setFrequency(pitch);
|
f@0
|
126 }
|
f@0
|
127
|
f@0
|
128 public float getFrequency(float freq){
|
f@0
|
129 return player.getFrequency();
|
f@0
|
130 }
|
f@0
|
131
|
f@0
|
132 @Override
|
f@0
|
133 public void start(){
|
f@0
|
134 player.start();
|
f@0
|
135 }
|
f@0
|
136
|
f@0
|
137
|
f@0
|
138 @Override
|
f@0
|
139 public void setLen(float sustainValue, float decayTime){
|
f@0
|
140 /* if decayTime is long enough, smooth out the attack to avoid glitchy sound */
|
f@0
|
141 if(Float.compare(decayTime,ATTACK_TIME_MS) > 0){
|
f@0
|
142 env = new Envelope(context,0.0f); // starts from 0
|
f@0
|
143 env.addSegment(sustainValue,ATTACK_TIME_MS,2); // attack
|
f@0
|
144 env.addSegment(0.0f,decayTime-ATTACK_TIME_MS, this); // decay
|
f@0
|
145 }else{
|
f@0
|
146 env = new Envelope(context,sustainValue);
|
f@0
|
147 env.addSegment(0.0f, decayTime, this); // decay
|
f@0
|
148 }
|
f@0
|
149 gain.setGain(env);
|
f@0
|
150 }
|
f@0
|
151
|
f@0
|
152 @Override
|
f@0
|
153 public void addLen(float sustainValue, float duration, final Bead bead){
|
f@0
|
154 if(env == null){
|
f@0
|
155 if(Float.compare(duration,ATTACK_TIME_MS) > 0){
|
f@0
|
156 env = new Envelope(context,0.0f); // starts from 0
|
f@0
|
157 env.addSegment(sustainValue,ATTACK_TIME_MS,2); // attack
|
f@0
|
158 env.addSegment(sustainValue,duration-ATTACK_TIME_MS, bead); // decay
|
f@0
|
159 }else{
|
f@0
|
160 env = new Envelope(context,sustainValue);
|
f@0
|
161 env.addSegment(0.0f, duration, bead); // decay
|
f@0
|
162 }
|
f@0
|
163 gain.setGain(env);
|
f@0
|
164 }else{
|
f@0
|
165 env.addSegment(sustainValue,duration, bead);
|
f@0
|
166 }
|
f@0
|
167
|
f@0
|
168 }
|
f@0
|
169
|
f@0
|
170 @Override
|
f@0
|
171 public void addLen(float sustainValue, float duration ){
|
f@0
|
172 if(env == null){
|
f@0
|
173 if(Float.compare(duration,ATTACK_TIME_MS) > 0){
|
f@0
|
174 env = new Envelope(context,0.0f); // starts from 0
|
f@0
|
175 env.addSegment(sustainValue,ATTACK_TIME_MS,2); // attack
|
f@0
|
176 env.addSegment(sustainValue,duration-ATTACK_TIME_MS, this); // decay
|
f@0
|
177 }else{
|
f@0
|
178 env = new Envelope(context,sustainValue);
|
f@0
|
179 env.addSegment(sustainValue, duration, this); // decay
|
f@0
|
180 }
|
f@0
|
181 gain.setGain(env);
|
f@0
|
182 }else{
|
f@0
|
183 env.addSegment(0.0f,duration, this);
|
f@0
|
184 }
|
f@0
|
185
|
f@0
|
186 }
|
f@0
|
187
|
f@0
|
188 @Override
|
f@0
|
189 public void messageReceived(Bead b){
|
f@0
|
190 kill();
|
f@0
|
191 }
|
f@0
|
192
|
f@0
|
193 }
|
f@0
|
194
|
f@0
|
195 @Override
|
f@0
|
196 public void renderCurve(Sequence m, float startTime) {
|
f@0
|
197 throw new UnsupportedOperationException();
|
f@0
|
198 }
|
f@0
|
199 };; |