f@0: /*
f@0: Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation.
f@0:
f@0: Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)
f@0:
f@0: This program is free software: you can redistribute it and/or modify
f@0: it under the terms of the GNU General Public License as published by
f@0: the Free Software Foundation, either version 3 of the License, or
f@0: (at your option) any later version.
f@0:
f@0: This program is distributed in the hope that it will be useful,
f@0: but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0: GNU General Public License for more details.
f@0:
f@0: You should have received a copy of the GNU General Public License
f@0: along with this program. If not, see .
f@0: */
f@0: package uk.ac.qmul.eecs.depic.daw.referencesound;
f@0:
f@0: import net.beadsproject.beads.core.AudioContext;
f@0: import net.beadsproject.beads.core.Bead;
f@0: import net.beadsproject.beads.core.UGen;
f@0: import net.beadsproject.beads.data.Buffer;
f@0: import net.beadsproject.beads.ugens.Envelope;
f@0: import net.beadsproject.beads.ugens.Gain;
f@0: import net.beadsproject.beads.ugens.WavePlayer;
f@0: import uk.ac.qmul.eecs.depic.patterns.Range;
f@0: import uk.ac.qmul.eecs.depic.patterns.Sequence;
f@0:
f@0: /**
f@0: * Implements a sequence mapping using beads engine and simple wave tables ugens
f@0: *
f@0: *
f@0: */
f@0: class BeadsWaveTableSequenceMapping extends BeadsSequenceMapping {
f@0: private Range renderCurvePitchSpan;
f@0: private Range renderValuePitchSpan;
f@0: private static final float ATTACK_TIME_MS = 5.0f;
f@0:
f@0: static {
f@0: /* loads the buffer for the PeakLevelPitchedUgen and stores it into staticBuffs */
f@0: int bufferLen = 4096;
f@0: Buffer pulse = new Buffer(bufferLen);
f@0: int pulseWidth = bufferLen/10;
f@0:
f@0: for(int i=0; i curvePitchSpan, Range valuePitchSpan){
f@0: super(ac);
f@0: renderCurvePitchSpan = curvePitchSpan;
f@0: renderValuePitchSpan = valuePitchSpan;
f@0: }
f@0:
f@0: @Override
f@0: protected PitchedUGen createRenderValueUGen(){
f@0: return new BufferPitchedUGen(ac, renderValuePitchSpan, Buffer.SINE);
f@0: }
f@0:
f@0: @Override
f@0: protected PitchedUGen createRenderCurveUGen(){
f@0: return new BufferPitchedUGen(ac, renderCurvePitchSpan, Buffer.SINE);
f@0: }
f@0:
f@0:
f@0: @Override
f@0: protected Range getRenderValuePitchSpan() {
f@0: return renderValuePitchSpan;
f@0: }
f@0:
f@0: @Override
f@0: protected Range getRenderCurvePitchSpan() {
f@0: return renderCurvePitchSpan;
f@0: }
f@0:
f@0: private class BufferPitchedUGen extends PitchedUGen {
f@0: private Gain gain;
f@0: private WavePlayer player;
f@0: private float maxFreq;
f@0: private float minFreq;
f@0: private Envelope env;
f@0:
f@0: /**
f@0: *
f@0: * Pulse TriangularBuffer Square Saw Noise Sine
f@0: *
f@0: * @param ac
f@0: * @param pitchSpan
f@0: * @param buffer
f@0: */
f@0: public BufferPitchedUGen(AudioContext ac, Range pitchSpan, Buffer buffer) {
f@0: super(ac);
f@0: if(maxFreq < minFreq){
f@0: throw new IllegalArgumentException("minFreq must be lower than maxFreq. minFreq: "+minFreq+" maxFreq:"+maxFreq );
f@0: }
f@0:
f@0: this.minFreq = pitchSpan.getStart();
f@0: this.maxFreq = pitchSpan.getEnd();
f@0: gain = new Gain(ac, 1, 0.5f);
f@0: player = new WavePlayer(ac,minFreq,buffer);
f@0:
f@0: gain.addInput(player);
f@0:
f@0: addToChainOutput(gain);
f@0: }
f@0:
f@0: @Override
f@0: public void setPitch(float pitch){
f@0: /* set the frequency for both the actual curve sound and the threshold sound */
f@0: player.setFrequency(pitch);
f@0:
f@0: }
f@0:
f@0: @Override
f@0: public void setPitch(UGen pitch) {
f@0: player.setFrequency(pitch);
f@0: }
f@0:
f@0: public float getFrequency(float freq){
f@0: return player.getFrequency();
f@0: }
f@0:
f@0: @Override
f@0: public void start(){
f@0: player.start();
f@0: }
f@0:
f@0:
f@0: @Override
f@0: public void setLen(float sustainValue, float decayTime){
f@0: /* if decayTime is long enough, smooth out the attack to avoid glitchy sound */
f@0: if(Float.compare(decayTime,ATTACK_TIME_MS) > 0){
f@0: env = new Envelope(context,0.0f); // starts from 0
f@0: env.addSegment(sustainValue,ATTACK_TIME_MS,2); // attack
f@0: env.addSegment(0.0f,decayTime-ATTACK_TIME_MS, this); // decay
f@0: }else{
f@0: env = new Envelope(context,sustainValue);
f@0: env.addSegment(0.0f, decayTime, this); // decay
f@0: }
f@0: gain.setGain(env);
f@0: }
f@0:
f@0: @Override
f@0: public void addLen(float sustainValue, float duration, final Bead bead){
f@0: if(env == null){
f@0: if(Float.compare(duration,ATTACK_TIME_MS) > 0){
f@0: env = new Envelope(context,0.0f); // starts from 0
f@0: env.addSegment(sustainValue,ATTACK_TIME_MS,2); // attack
f@0: env.addSegment(sustainValue,duration-ATTACK_TIME_MS, bead); // decay
f@0: }else{
f@0: env = new Envelope(context,sustainValue);
f@0: env.addSegment(0.0f, duration, bead); // decay
f@0: }
f@0: gain.setGain(env);
f@0: }else{
f@0: env.addSegment(sustainValue,duration, bead);
f@0: }
f@0:
f@0: }
f@0:
f@0: @Override
f@0: public void addLen(float sustainValue, float duration ){
f@0: if(env == null){
f@0: if(Float.compare(duration,ATTACK_TIME_MS) > 0){
f@0: env = new Envelope(context,0.0f); // starts from 0
f@0: env.addSegment(sustainValue,ATTACK_TIME_MS,2); // attack
f@0: env.addSegment(sustainValue,duration-ATTACK_TIME_MS, this); // decay
f@0: }else{
f@0: env = new Envelope(context,sustainValue);
f@0: env.addSegment(sustainValue, duration, this); // decay
f@0: }
f@0: gain.setGain(env);
f@0: }else{
f@0: env.addSegment(0.0f,duration, this);
f@0: }
f@0:
f@0: }
f@0:
f@0: @Override
f@0: public void messageReceived(Bead b){
f@0: kill();
f@0: }
f@0:
f@0: }
f@0:
f@0: @Override
f@0: public void renderCurve(Sequence m, float startTime) {
f@0: throw new UnsupportedOperationException();
f@0: }
f@0: };;