CSL  6.0
DelayLine.cpp
Go to the documentation of this file.
1 //
2 // DLine.h -- an Interpolating Delay Line
3 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
4 //
5 // This is a typical circular buffer with one writer and multiple readers (tap instances)
6 
7 #include "DelayLine.h"
8 
9 using namespace csl;
10 
11 // DelayLine implementation
12 DelayLine :: DelayLine(unsigned maxDelayInSamples) : UnitGenerator(), Effect() {
13  // add a little bit of wiggle room to the delay length this is necessary to make setDelayLength work
14  mMaxDelayInSamples = maxDelayInSamples;
15  mTotalDelayInSamples = maxDelayInSamples + CGestalt::maxBufferFrames();
16  mRingBuffer.mBuffer.setSize(CGestalt::numOutChannels(), mTotalDelayInSamples); // Prepare the buffer to be used for storage.
17  mRingBuffer.mBuffer.allocateMonoBuffers(); // Allocate memory for my buffer.
18 }
19 
22  if (length < 0)
23  length += mTotalDelayInSamples;
24  return (unsigned)length;
25 }
26 
27 // change the delay length and return the new value
28 unsigned DelayLine::setDelayLength(unsigned delayInSamples) {
29 
30  if (delayInSamples > mMaxDelayInSamples) {
31  logMsg(kLogError, "Cannot set delay line length: asked for %d in line of length %d", delayInSamples, mMaxDelayInSamples);
32  return delayLength();
33  }
34  mRingBuffer.mTap.seekTo(delayInSamples, kPositionStart); // Cue the read head (tap) to the new position.
35  return delayLength();
36 }
37 
38 // change the delay length and return the new value
39 float DelayLine::setDelayTime(float delayInMiliseconds) {
40  unsigned delayInSamples = (unsigned)(delayInMiliseconds * mFrameRate / 1000); // Converting ms to samples.
41 
42  if (delayInSamples > mMaxDelayInSamples) { // If larger than the maximum size specified, keep last value and print an error.
43  logMsg(kLogError, "Cannot set delay line length: asked for %d in line of length %d", delayInSamples, mMaxDelayInSamples);
44  return (delayLength() * (float)mFrameRate / 1000); // Converting back to miliseconds.
45  }
46  mRingBuffer.mTap.seekTo(delayInSamples, kPositionStart); // Cue the read head (tap) to the new position.
47  return delayInMiliseconds; // If everything went well, return the requested value.
48 }
49 
50 // The next_buffer call writes, then reads
51 void DelayLine::nextBuffer(Buffer& output) throw(Exception) {
52  getInput(output);
53  mRingBuffer.writeBuffer(output);
54  mRingBuffer.nextBuffer(output);
55  return;
56 }
57 
58 
59 //
60 //
61 //
62 //DLine :: DLine ( FrameStream &input, float max_delay ) : Processor(input),
63 // max_delay_time(max_delay),
64 // delay_time(0.5 * max_delay),
65 // max_delay_in_frames( (unsigned) (_sampleRate * max_delay + CGestalt::block_size() ) ),
66 // interp_type(kTruncate),
67 // start_frame(0),
68 //// end_frame(0),
69 // write_frame(0),
70 // ring_buffer(FrameStream::channels(), max_delay_in_frames)
71 //{
72 //// max_delay_in_frames = _sampleRate * max_delay;
73 // ring_buffer.allocate_mono_buffers();
74 // ring_buffer.zero_buffers();
75 //
76 //}
77 //
78 //DLine :: ~DLine() {
79 // ring_buffer.free_mono_buffers();
80 //}
81 //
82 //bool DLine :: init_delay_time( float dt ) {
83 // if (dt > max_delay_time)
84 // return false;
85 // delay_time = dt;
86 // return set_target_delay_time(dt);
87 //}
88 //
89 //bool DLine :: set_target_delay_time( float tdt ) {
90 // if (tdt > max_delay_time)
91 // return false;
92 // target_delay_time = tdt;
93 // return true;
94 //}
95 //
96 //bool DLine :: set_interp_type( InterpType it ) {
97 // interp_type = it;
98 // return true;
99 //}
100 //
101 //// Do the work
102 //
103 //status DLine :: mono_next_buffer(Buffer & inputBuffer, Buffer & outputBuffer, unsigned inBufNum, unsigned outBufNum) {
104 // unsigned temp_write_frame = write_frame;
105 // sample * rbPtr = ring_buffer._monoBuffers[outBufNum] + temp_write_frame;
106 // sample * outPtr = outputBuffer._monoBuffers[outBufNum];
107 ///*
108 // for (int i=0; i<outputBuffer._numFrames; i++){
109 // // ring_buffer._monoBuffers[outBufNum][temp_write_frame] = outputBuffer._monoBuffers[outBufNum][i];
110 // *rbPtr++ = *outPtr++
111 // if (++temp_write_frame >= ring_buffer._numFrames)
112 // temp_write_frame = 0;
113 // rbPtr = ring_buffer._monoBuffers[outBufNum];
114 // }
115 //*/
116 // sample *tempSamplePtr;
117 // outPtr = outputBuffer._monoBuffers[outBufNum];
118 // float ramp_factor = 0.0001; // ??
119 // rbPtr = ring_buffer._monoBuffers[outBufNum];
120 // for (unsigned i = 0; i < outputBuffer._numFrames; i++) {
121 // delay_time = (1.0 - ramp_factor) * delay_time + ramp_factor * target_delay_time;
122 // float r_index_and_mant = (delay_time * _sampleRate);
123 // unsigned index = (unsigned) floor(r_index_and_mant);
124 // float mantissa = r_index_and_mant - index;
125 // int read_frame = temp_write_frame - index;
126 // while (read_frame < 0)
127 // read_frame += ring_buffer._numFrames;
128 // sample lower_read_value = *(rbPtr + read_frame);
129 // tempSamplePtr = ((unsigned)(rbPtr + read_frame + 1)) % ring_buffer._numFrames;
130 // sample upper_read_value = *tempSamplePtr;
131 // if ( ++temp_write_frame >= ring_buffer._numFrames)
132 // temp_write_frame -= ring_buffer._numFrames;
133 // *outPtr++ = ((1.0 - mantissa) * lower_read_value) + (mantissa * upper_read_value);
134 // }
135 // write_frame = temp_write_frame;
136 //}
137 //
138 //// Call inherited version
139 //
140 //status DLine :: next_buffer(Buffer & inputBuffer, Buffer & outputBuffer){
141 // Processor :: pull_input( inputBuffer, outputBuffer );
142 // FrameStream :: next_buffer( inputBuffer, outputBuffer );
143 //// update_write_frame(outputBuffer._numFrames);
144 // write_frame += outputBuffer._numFrames;
145 // write_frame %= ring_buffer._numFrames;
146 //
147 //}
148 //
149 //
150 //
151 //
void logMsg(const char *format,...)
These are the public logging messages.
Definition: CGestalt.cpp:292
RingBuffer mRingBuffer
Definition: DelayLine.h:30
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
Definition: Accessor.h:17
Effect – mix-in for classes that have unit generators as inputs (like filters).
Definition: CSL_Core.h:466
static unsigned numOutChannels()
default number of output channels
Definition: CGestalt.cpp:59
unsigned mFrameRate
trigger ignored here
Definition: CSL_Core.h:288
unsigned mTotalDelayInSamples
Definition: DelayLine.h:32
static unsigned maxBufferFrames()
the max num frames that can be requested
Definition: CGestalt.cpp:54
RingBufferTap mTap
internal tap so a RingBuffer can also be a a UnitGenerator
Definition: RingBuffer.h:67
void setSize(unsigned numChannels, unsigned numFrames)
Definition: CSL_Core.cpp:75
DelayLine(unsigned maxDelayInSamples)
Definition: DelayLine.cpp:12
unsigned delayLength()
Definition: DelayLine.cpp:20
unsigned mMaxDelayInSamples
Definition: DelayLine.h:31
unsigned mCurrentFrame
where I currently am in the buffer
Definition: CSL_Core.h:580
Buffer mBuffer
Definition: RingBuffer.h:66
unsigned seekTo(int position, SeekPosition whence)
general-purpose seek on a stream
Definition: RingBuffer.cpp:138
unsigned setDelayLength(unsigned delayInSamples)
Definition: DelayLine.cpp:28
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
Definition: CSL_Core.h:106
void nextBuffer(Buffer &output)
get a buffer of Frames – this is the core CSL "pull" function; the given buffer can be written into...
Definition: DelayLine.cpp:51
forward declaration
Definition: CSL_Core.h:241
float setDelayTime(float delayInMiliseconds)
Definition: DelayLine.cpp:39
unsigned mCurrentWriteFrame
state – users can manipulate my internal tap and buffer
Definition: RingBuffer.h:65