public WaveGenerator(IEnumerable <Note> notes) { // Init chunks header = new WaveHeader(); format = new WaveFormatChunk(); data = new WaveDataChunk(); var milliseconds = notes.Select((x) => x.Duration.TotalMilliseconds).Sum(); //var seconds = (uint)(milliseconds / 1000); // Number of samples = sample rate * channels * bytes per sample // Multiply first, then divide to avoid rounding errors uint numSamples = (uint)(((format.dwSamplesPerSec * milliseconds) / 1000) * format.wChannels); // Initialize the 16-bit array data.shortArray = new short[numSamples]; int amplitude = 32760; // Max amplitude for 16-bit audio uint sampleCount = 0; foreach (var n in notes) { // The "angle" used in the function, adjusted for the number of channels and sample rate. // This value is like the period of the wave. double t = (Math.PI * 2 * n.Frequency) / (format.dwSamplesPerSec * format.wChannels); var samplesThisNote = format.dwSamplesPerSec * format.wChannels * n.Duration.TotalSeconds; // Loop over sampleCount rather than from 0, because you don't want to reset // the sine wave for repeated notes of the same pitch for (uint i = sampleCount; i < (samplesThisNote + sampleCount) - 1; i++) { // Fill with a simple sine wave at max amplitude for (int channel = 0; channel < format.wChannels; channel++) { data.shortArray[i + channel] = Convert.ToInt16(amplitude * Math.Sin(t * i)); } } sampleCount += (uint)samplesThisNote; } // Calculate data chunk size in bytes data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8)); }
/// <summary> /// Initializes the object and generates a wave. /// </summary> /// <param name="type">The type of wave to generate</param> public WaveGenerator(WaveExampleType type, double freq, uint seconds) { // Init chunks header = new WaveHeader(); format = new WaveFormatChunk(); data = new WaveDataChunk(); // Fill the data array with sample data switch (type) { case WaveExampleType.ExampleSineWave: // Number of samples = sample rate * channels * bytes per sample uint numSamples = format.dwSamplesPerSec * format.wChannels * seconds; // Initialize the 16-bit array data.shortArray = new short[numSamples]; int amplitude = 32760; // Max amplitude for 16-bit audio // The "angle" used in the function, adjusted for the number of channels and sample rate. // This value is like the period of the wave. double t = (Math.PI * 2 * freq) / (format.dwSamplesPerSec * format.wChannels); for (uint i = 0; i < numSamples - 1; i++) { // Fill with a simple sine wave at max amplitude for (int channel = 0; channel < format.wChannels; channel++) { data.shortArray[i + channel] = Convert.ToInt16(amplitude * Math.Sin(t * i)); } } // Calculate data chunk size in bytes data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8)); break; } }
public WaveGenerator(IEnumerable<Note> notes) { // Init chunks header = new WaveHeader(); format = new WaveFormatChunk(); data = new WaveDataChunk(); var milliseconds = notes.Select((x) => x.Duration.TotalMilliseconds).Sum(); //var seconds = (uint)(milliseconds / 1000); // Number of samples = sample rate * channels * bytes per sample // Multiply first, then divide to avoid rounding errors uint numSamples = (uint)(((format.dwSamplesPerSec * milliseconds) / 1000) * format.wChannels); // Initialize the 16-bit array data.shortArray = new short[numSamples]; int amplitude = 32760; // Max amplitude for 16-bit audio uint sampleCount = 0; foreach (var n in notes) { // The "angle" used in the function, adjusted for the number of channels and sample rate. // This value is like the period of the wave. double t = (Math.PI * 2 * n.Frequency) / (format.dwSamplesPerSec * format.wChannels); var samplesThisNote = format.dwSamplesPerSec * format.wChannels * n.Duration.TotalSeconds; // Loop over sampleCount rather than from 0, because you don't want to reset // the sine wave for repeated notes of the same pitch for (uint i = sampleCount; i < (samplesThisNote + sampleCount) - 1; i++) { // Fill with a simple sine wave at max amplitude for (int channel = 0; channel < format.wChannels; channel++) { data.shortArray[i + channel] = Convert.ToInt16(amplitude * Math.Sin(t * i)); } } sampleCount += (uint)samplesThisNote; } // Calculate data chunk size in bytes data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8)); }