Example #1
0
        public void Play()
        {
            var          mStrm  = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(mStrm);

            int   msDuration       = GetDuration() * 60;
            int   formatChunkSize  = 16;
            int   headerSize       = 8;
            short formatType       = 1;
            short tracks           = 1;
            int   samplesPerSecond = 44100;
            short bitsPerSample    = 16;
            short frameSize        = (short)(tracks * ((bitsPerSample + 7) / 8));
            int   bytesPerSecond   = samplesPerSecond * frameSize;
            int   waveSize         = 4;
            int   samples          = (int)((decimal)samplesPerSecond * msDuration / 1000);
            int   dataChunkSize    = samples * frameSize;
            int   fileSize         = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize;

            {
                // var encoding = new System.Text.UTF8Encoding();
                writer.Write(0x46464952); // = encoding.GetBytes("RIFF")
                writer.Write(fileSize);
                writer.Write(0x45564157); // = encoding.GetBytes("WAVE")
                writer.Write(0x20746D66); // = encoding.GetBytes("fmt ")
                writer.Write(formatChunkSize);
                writer.Write(formatType);
                writer.Write(tracks);
                writer.Write(samplesPerSecond);
                writer.Write(bytesPerSecond);
                writer.Write(frameSize);
                writer.Write(bitsPerSample);
                writer.Write(0x61746164); // = encoding.GetBytes("data")
                writer.Write(dataChunkSize);
            }

            foreach (Measure measure in mMeasures)
            {
                for (int c = 0; c < measure.GetChordCount(); c++)
                {
                    Chord chord = measure.GetChord(c);
                    if (chord.GetNote(0).GetPitch() != Pitch.Rest)
                    {
                        double[] angles               = new double[chord.GetNoteCount()];
                        ushort[] frequency            = new ushort[chord.GetNoteCount()];
                        int[]    samplesPerWavelength = new int[chord.GetNoteCount()];
                        short[]  ampSteps             = new short[chord.GetNoteCount()];
                        int      chordSamples         = (int)((decimal)samplesPerSecond * (int)chord.GetDuration() * 60 / 1000);

                        ushort volume = 16383;
                        if (chord.GetWaveForm() == WaveForm.Square)
                        {
                            volume /= 2;
                        }

                        const double TAU           = 2 * Math.PI;
                        double       NOTE_CONSTANT = Math.Pow(2, (1.0 / 12.0));

                        double amp = volume / 2;

                        for (int i = 0; i < chord.GetNoteCount(); i++)
                        {
                            double step = (int)Pitch.A;
                            if (chord.GetNote(i).GetPitch() < Pitch.E)
                            {
                                step -= 0.5;
                            }
                            step += (chord.GetNote(i).Octave - 4) * 6;
                            double exp = -2 * ((double)chord.GetNote(i).GetPitch() - step);

                            frequency[i]            = (ushort)(440 * Math.Pow(NOTE_CONSTANT, exp));
                            samplesPerWavelength[i] = bytesPerSecond / frequency[i];
                            ampSteps[i]             = (short)(amp * 2 / samplesPerWavelength[i]);
                        }

                        for (int i = 0; i < angles.Length; i++)
                        {
                            angles[i] = frequency[i] * TAU / samplesPerSecond;
                        }

                        short tempSample = (short)-amp;
                        for (int i = 0; i < chordSamples; i++)
                        {
                            short s = 0;

                            switch (chord.GetWaveForm())
                            {
                            case WaveForm.Sine:
                                foreach (double theta in angles)
                                {
                                    s += (short)(amp * Math.Sin(theta * i));
                                }
                                break;

                            case WaveForm.Square:
                                foreach (double theta in angles)
                                {
                                    s += (short)(amp * Math.Sign(Math.Sin(theta * i)));
                                }
                                break;

                            case WaveForm.Sawtooth:
                                foreach (short ampStep in ampSteps)
                                {
                                    tempSample += ampStep;
                                    s          += (short)(tempSample / ampSteps.Length);
                                }
                                break;

                            case WaveForm.Triangle:
                                for (int j = 0; j < ampSteps.Length; j++)
                                {
                                    if (Math.Abs(tempSample) > amp)
                                    {
                                        ampSteps[j] = (short)-ampSteps[j];
                                    }

                                    tempSample += ampSteps[j];
                                    s          += (short)(tempSample / ampSteps.Length);
                                }
                                break;

                            case WaveForm.Noise:
                                s += (short)((new Random().NextDouble() * 2 - 1) * amp);
                                break;
                            }
                            writer.Write(s);
                        }
                    }
                }
            }

            mStrm.Seek(0, SeekOrigin.Begin);
            new System.Media.SoundPlayer(mStrm).Play();
            writer.Close();
            mStrm.Close();
        }
Example #2
0
        public void ExportAudio(string filename)
        {
            BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create));

            Random RG = new Random();

            int   msDuration       = GetDuration() * 3600 / BPM;
            int   formatChunkSize  = 16;
            int   headerSize       = 8;
            short formatType       = 1;
            short tracks           = 1;
            int   samplesPerSecond = 44100;
            short bitsPerSample    = 16;
            short frameSize        = (short)(tracks * ((bitsPerSample + 7) / 8));
            int   bytesPerSecond   = samplesPerSecond * frameSize;
            int   waveSize         = 4;
            int   samples          = (int)((decimal)samplesPerSecond * msDuration / 1000);
            int   dataChunkSize    = samples * frameSize;
            int   fileSize         = waveSize + headerSize + formatChunkSize + headerSize + dataChunkSize;

            {
                // var encoding = new System.Text.UTF8Encoding();
                writer.Write(0x46464952); // = encoding.GetBytes("RIFF")
                writer.Write(fileSize);
                writer.Write(0x45564157); // = encoding.GetBytes("WAVE")
                writer.Write(0x20746D66); // = encoding.GetBytes("fmt ")
                writer.Write(formatChunkSize);
                writer.Write(formatType);
                writer.Write(tracks);
                writer.Write(samplesPerSecond);
                writer.Write(bytesPerSecond);
                writer.Write(frameSize);
                writer.Write(bitsPerSample);
                writer.Write(0x61746164); // = encoding.GetBytes("data")
                writer.Write(dataChunkSize);
            }

            for (int sz = 0; sz < stanzas; sz++)
            {
                short[] preSamples = new short[samples];
                for (int inst = GetInstrumentCount() * sz / stanzas; inst < GetInstrumentCount() * (sz + 1) / stanzas; inst++)
                {
                    Instrument instrument = GetInstrument(inst);
                    for (int st = 0; st < instrument.GetStaffCount(); st++)
                    {
                        int   chordNumber = 0;
                        Staff staff       = instrument.GetStaff(st);
                        for (int m = 0; m < staff.GetMeasureCount(); m++)
                        {
                            Measure measure = staff.GetMeasure(m);
                            for (int c = 0; c < measure.GetChordCount(); c++)
                            {
                                Chord chord = measure.GetChord(c);

                                double[] angles               = new double[chord.GetNoteCount()];
                                ushort[] frequency            = new ushort[chord.GetNoteCount()];
                                int[]    samplesPerWavelength = new int[chord.GetNoteCount()];
                                short[]  ampSteps             = new short[chord.GetNoteCount()];
                                int      chordSamples         = (int)((decimal)samplesPerSecond * (int)chord.GetDuration() * 3600 / BPM / 1000);

                                ushort volume = 16383;
                                if (chord.GetWaveForm() == WaveForm.Square)
                                {
                                    volume /= 2;
                                }

                                const double TAU           = 2 * Math.PI;
                                double       NOTE_CONSTANT = Math.Pow(2, (1.0 / 12.0));

                                double amp = volume / 2;

                                for (int n = 0; n < chord.GetNoteCount(); n++)
                                {
                                    double step = (int)Pitch.A;
                                    if (chord.GetNote(n).GetPitch() < Pitch.E)
                                    {
                                        step -= 0.5;
                                    }
                                    step += (chord.GetNote(n).Octave - 4) * 6;
                                    double exp = -2 * ((double)chord.GetNote(n).GetPitch() - step);

                                    frequency[n]            = (ushort)(440 * Math.Pow(NOTE_CONSTANT, exp));
                                    samplesPerWavelength[n] = bytesPerSecond / frequency[n];
                                    ampSteps[n]             = (short)(amp * 2 / samplesPerWavelength[n]);
                                }

                                for (int n = 0; n < chord.GetNoteCount(); n++)
                                {
                                    angles[n] = frequency[n] * TAU / samplesPerSecond;
                                }

                                short tempSample = (short)-amp;
                                for (int s = 0; s < chordSamples; s++)
                                {
                                    short sample = 0;

                                    if (chord.GetNote(0).GetPitch() != Pitch.Rest)
                                    {
                                        switch (chord.GetWaveForm())
                                        {
                                        case WaveForm.Sine:
                                            for (int n = 0; n < chord.GetNoteCount(); n++)
                                            {
                                                sample += (short)(amp * Math.Sin(angles[n] * s));
                                            }
                                            break;

                                        case WaveForm.Square:
                                            for (int n = 0; n < chord.GetNoteCount(); n++)
                                            {
                                                sample += (short)(amp * Math.Sign(Math.Sin(angles[n] * s)));
                                            }
                                            break;

                                        case WaveForm.Sawtooth:
                                            for (int n = 0; n < chord.GetNoteCount(); n++)
                                            {
                                                sample += (short)(s % samplesPerWavelength[n] * ampSteps[n]);
                                            }
                                            break;

                                        case WaveForm.Triangle:
                                            for (int n = 0; n < chord.GetNoteCount(); n++)
                                            {
                                                int sLoc = s % samplesPerWavelength[n];
                                                if (sLoc < samplesPerWavelength[n] / 2)
                                                {
                                                    if (sLoc < samplesPerWavelength[n] / 4)
                                                    {
                                                        sample += (short)(sLoc * ampSteps[n]);
                                                    }
                                                    else
                                                    {
                                                        sample += (short)((samplesPerWavelength[n] - sLoc) * ampSteps[n]);
                                                    }
                                                }
                                                else
                                                if (sLoc < samplesPerWavelength[n] * 3 / 4)
                                                {
                                                    sample += (short)(sLoc * ampSteps[n]);
                                                }
                                                else
                                                {
                                                    sample += (short)((samplesPerWavelength[n] - sLoc) * ampSteps[n]);
                                                }
                                            }
                                            break;

                                        case WaveForm.Noise:
                                            sample += (short)RG.Next((int)-amp, (int)amp);
                                            break;
                                        }
                                    }

                                    preSamples[chordNumber] += sample;
                                    chordNumber++;
                                }
                            }
                        }
                    }
                }

                foreach (short s in preSamples)
                {
                    writer.Write(s);
                }
            }

            writer.Close();
        }