public void CacheSamples() { while(_currentSynthesizedSample < (uint)envelopeFullLength) { //TODO: error checking, exceptions, etc... SynthesizedBuffer buffer = new SynthesizedBuffer(); buffer.samples = new float[this.BufferSize]; //initialize buffer for(int i = 0; i < buffer.samples.Length; i++) buffer.samples[i] = 0.0f; bool finished = false; //for (int i = 0; i < samples.Length; i++) for(long counter = 0; counter < this.BufferSize; counter++) { if (finished) break; // Repeats every _repeatLimit times, partially resetting the sound parameters if(repeatLimit != 0) { if(++repeatTime >= repeatLimit) { repeatTime = 0; Reset(false); } } // If _changeLimit is reached, shifts the pitch if(changeLimit != 0) { if(++changeTime >= changeLimit) { changeLimit = 0; period *= changeAmount; } } // Acccelerate and apply slide slide += deltaSlide; period *= slide; // Checks for frequency getting too low, and stops the sound if a minFrequency was set if(period > maxPeriod) { period = maxPeriod; if(minFrequency > 0.0) finished = true; } periodTemp = period; // Applies the vibrato effect if(vibratoAmplitude > 0.0) { vibratoPhase += vibratoSpeed; periodTemp = period * (float)(1.0 + Math.Sin(vibratoPhase) * vibratoAmplitude); } periodTemp = (int)periodTemp; if(periodTemp < 8) periodTemp = 8; // Sweeps the square duty if (waveType == 0) { squareDuty += dutySweep; if(squareDuty < 0.0f) squareDuty = 0.0f; else if (squareDuty > 0.5f) squareDuty = 0.5f; } // Moves through the different stages of the volume envelope if(++envelopeTime > envelopeLength) { envelopeTime = 0; switch(++envelopeStage) { case 1: envelopeLength = envelopeLength1; break; case 2: envelopeLength = envelopeLength2; break; } } // Sets the volume based on the position in the envelope switch(envelopeStage) { case 0: envelopeVolume = envelopeTime * envelopeOverLength0; break; case 1: envelopeVolume = 1.0f + (1.0f - envelopeTime * envelopeOverLength1) * 2.0f * sustainPunch; break; case 2: envelopeVolume = 1.0f - envelopeTime * envelopeOverLength2; break; case 3: envelopeVolume = 0.0f; finished = true; break; } // Moves the phaser offset if (phaser) { phaserOffset += phaserDeltaOffset; phaserInt = (int)phaserOffset; if(phaserInt < 0) phaserInt = -phaserInt; else if (phaserInt > 1023) phaserInt = 1023; } // Moves the high-pass filter cutoff if(filters && hpFilterDeltaCutoff != 0.0) { hpFilterCutoff *= hpFilterDeltaCutoff; if(hpFilterCutoff < 0.00001f) hpFilterCutoff = 0.00001f; else if(hpFilterCutoff > 0.1f) hpFilterCutoff = 0.1f; } superSample = 0.0f; for(int j = 0; j < 8; j++) { // Cycles through the period phase++; if(phase >= periodTemp) { phase = phase - (int)periodTemp; // Generates new random noise for this period if(waveType == WaveType.Noise) { for(int n=0; n<32; n++) noiseBuffer[n] = (float)random.NextDouble() * 2.0f - 1.0f; } } // Gets the sample from the oscillator switch(waveType) { case WaveType.Square: // Square wave { sample = ((phase / periodTemp) < squareDuty) ? 0.5f : -0.5f; break; } case WaveType.Saw: // Saw wave { sample = 1.0f - (phase / periodTemp) * 2.0f; break; } case WaveType.Sin: // Sine wave (fast and accurate approx) { pos = phase / periodTemp; pos = pos > 0.5f ? (pos - 1.0f) * 6.28318531f : pos * 6.28318531f; sample = pos < 0 ? 1.27323954f * pos + .405284735f * pos * pos : 1.27323954f * pos - 0.405284735f * pos * pos; sample = sample < 0 ? .225f * (sample *-sample - sample) + sample : .225f * (sample * sample - sample) + sample; break; } case WaveType.Noise: // Noise { sample = noiseBuffer[(phase * 32 / (int)periodTemp) % 32]; break; } } // Applies the low and high pass filters if (filters) { lpFilterOldPos = lpFilterPos; lpFilterCutoff *= lpFilterDeltaCutoff; if(lpFilterCutoff < 0.0f) lpFilterCutoff = 0.0f; else if(lpFilterCutoff > 0.1f) lpFilterCutoff = 0.1f; if(lpFilterOn) { lpFilterDeltaPos += (sample - lpFilterPos) * lpFilterCutoff; lpFilterDeltaPos *= lpFilterDamping; } else { lpFilterPos = sample; lpFilterDeltaPos = 0.0f; } lpFilterPos += lpFilterDeltaPos; hpFilterPos += lpFilterPos - lpFilterOldPos; hpFilterPos *= 1.0f - hpFilterCutoff; sample = hpFilterPos; } // Applies the phaser effect if (phaser) { phaserBuffer[phaserPos & 1023] = sample; sample += phaserBuffer[(phaserPos - phaserInt + 1024) & 1023]; phaserPos = (phaserPos + 1) & 1023; } superSample += sample; } // Averages out the super samples and applies volumes superSample = masterVolume * envelopeVolume * superSample * 0.125f; // Clipping if too loud if(superSample > 1.0f) superSample = 1.0f; else if(superSample < -1.0f) superSample = -1.0f; buffer.samples[counter] = (float)superSample; _currentSynthesizedSample++; } _synthesizedBlocks.Enqueue(buffer); } //return new SoundEffect(byteSamples, 44100, AudioChannels.Mono); this.IsCached = true; this.IsReadyToPlay = true; _currentSynthesizedSample = 0; }
public void CacheSamples() { while (_currentSynthesizedSample < (uint)envelopeFullLength) { //TODO: error checking, exceptions, etc... SynthesizedBuffer buffer = new SynthesizedBuffer(); buffer.samples = new float[this.BufferSize]; //initialize buffer for (int i = 0; i < buffer.samples.Length; i++) { buffer.samples[i] = 0.0f; } bool finished = false; //for (int i = 0; i < samples.Length; i++) for (long counter = 0; counter < this.BufferSize; counter++) { if (finished) { break; } // Repeats every _repeatLimit times, partially resetting the sound parameters if (repeatLimit != 0) { if (++repeatTime >= repeatLimit) { repeatTime = 0; Reset(false); } } // If _changeLimit is reached, shifts the pitch if (changeLimit != 0) { if (++changeTime >= changeLimit) { changeLimit = 0; period *= changeAmount; } } // Acccelerate and apply slide slide += deltaSlide; period *= slide; // Checks for frequency getting too low, and stops the sound if a minFrequency was set if (period > maxPeriod) { period = maxPeriod; if (minFrequency > 0.0) { finished = true; } } periodTemp = period; // Applies the vibrato effect if (vibratoAmplitude > 0.0) { vibratoPhase += vibratoSpeed; periodTemp = period * (float)(1.0 + Math.Sin(vibratoPhase) * vibratoAmplitude); } periodTemp = (int)periodTemp; if (periodTemp < 8) { periodTemp = 8; } // Sweeps the square duty if (waveType == 0) { squareDuty += dutySweep; if (squareDuty < 0.0f) { squareDuty = 0.0f; } else if (squareDuty > 0.5f) { squareDuty = 0.5f; } } // Moves through the different stages of the volume envelope if (++envelopeTime > envelopeLength) { envelopeTime = 0; switch (++envelopeStage) { case 1: envelopeLength = envelopeLength1; break; case 2: envelopeLength = envelopeLength2; break; } } // Sets the volume based on the position in the envelope switch (envelopeStage) { case 0: envelopeVolume = envelopeTime * envelopeOverLength0; break; case 1: envelopeVolume = 1.0f + (1.0f - envelopeTime * envelopeOverLength1) * 2.0f * sustainPunch; break; case 2: envelopeVolume = 1.0f - envelopeTime * envelopeOverLength2; break; case 3: envelopeVolume = 0.0f; finished = true; break; } // Moves the phaser offset if (phaser) { phaserOffset += phaserDeltaOffset; phaserInt = (int)phaserOffset; if (phaserInt < 0) { phaserInt = -phaserInt; } else if (phaserInt > 1023) { phaserInt = 1023; } } // Moves the high-pass filter cutoff if (filters && hpFilterDeltaCutoff != 0.0) { hpFilterCutoff *= hpFilterDeltaCutoff; if (hpFilterCutoff < 0.00001f) { hpFilterCutoff = 0.00001f; } else if (hpFilterCutoff > 0.1f) { hpFilterCutoff = 0.1f; } } superSample = 0.0f; for (int j = 0; j < 8; j++) { // Cycles through the period phase++; if (phase >= periodTemp) { phase = phase - (int)periodTemp; // Generates new random noise for this period if (waveType == WaveType.Noise) { for (int n = 0; n < 32; n++) { noiseBuffer[n] = (float)random.NextDouble() * 2.0f - 1.0f; } } } // Gets the sample from the oscillator switch (waveType) { case WaveType.Square: // Square wave { sample = ((phase / periodTemp) < squareDuty) ? 0.5f : -0.5f; break; } case WaveType.Saw: // Saw wave { sample = 1.0f - (phase / periodTemp) * 2.0f; break; } case WaveType.Sin: // Sine wave (fast and accurate approx) { pos = phase / periodTemp; pos = pos > 0.5f ? (pos - 1.0f) * 6.28318531f : pos * 6.28318531f; sample = pos < 0 ? 1.27323954f * pos + .405284735f * pos * pos : 1.27323954f * pos - 0.405284735f * pos * pos; sample = sample < 0 ? .225f * (sample * -sample - sample) + sample : .225f * (sample * sample - sample) + sample; break; } case WaveType.Noise: // Noise { sample = noiseBuffer[(phase * 32 / (int)periodTemp) % 32]; break; } } // Applies the low and high pass filters if (filters) { lpFilterOldPos = lpFilterPos; lpFilterCutoff *= lpFilterDeltaCutoff; if (lpFilterCutoff < 0.0f) { lpFilterCutoff = 0.0f; } else if (lpFilterCutoff > 0.1f) { lpFilterCutoff = 0.1f; } if (lpFilterOn) { lpFilterDeltaPos += (sample - lpFilterPos) * lpFilterCutoff; lpFilterDeltaPos *= lpFilterDamping; } else { lpFilterPos = sample; lpFilterDeltaPos = 0.0f; } lpFilterPos += lpFilterDeltaPos; hpFilterPos += lpFilterPos - lpFilterOldPos; hpFilterPos *= 1.0f - hpFilterCutoff; sample = hpFilterPos; } // Applies the phaser effect if (phaser) { phaserBuffer[phaserPos & 1023] = sample; sample += phaserBuffer[(phaserPos - phaserInt + 1024) & 1023]; phaserPos = (phaserPos + 1) & 1023; } superSample += sample; } // Averages out the super samples and applies volumes superSample = masterVolume * envelopeVolume * superSample * 0.125f; // Clipping if too loud if (superSample > 1.0f) { superSample = 1.0f; } else if (superSample < -1.0f) { superSample = -1.0f; } buffer.samples[counter] = (float)superSample; _currentSynthesizedSample++; } _synthesizedBlocks.Enqueue(buffer); } //return new SoundEffect(byteSamples, 44100, AudioChannels.Mono); this.IsCached = true; this.IsReadyToPlay = true; _currentSynthesizedSample = 0; }