public static void WriteAudioFile(string key, string saveLocation)
        {
            double[,] audioWithHeader = Storage.SignalFromStorage(key);
            //Storage.SignalStorage.TryGetValue(key, out audioWithHeader);
            double[,] audioHeaderless = AudioStorageProcessing.RemoveHeader(audioWithHeader, out byte[] header);
            AudioStorageProcessing.WavSegmentFinder(header, out uint fmtChunkStart, out uint factChunkStart, out uint dataChunkStart, out uint headerSize);
            ushort channelAmount = ChannelAmount(header, fmtChunkStart);
            short  bytePerSample = (short)(BitsPerSample(header, fmtChunkStart) / 8);
            uint   dataLength    = (uint)(audioHeaderless.GetLength(0) * bytePerSample * channelAmount);

            Conversion.ValueToBitArrayQuick(dataLength, out byte[] dataSegmentSize);
            for (uint n = dataChunkStart + 4; n < dataChunkStart + 8; n++)
            {
                header[n] = dataSegmentSize[n - dataChunkStart - 4];
            }
            byte[]      audioByte = TimeDomainToByteArray(audioHeaderless, channelAmount, BitsPerSample(header, fmtChunkStart));
            List <byte> list      = new List <byte>(header.Length + audioByte.Length);

            list.AddRange(header);
            list.AddRange(audioByte);
            byte[] completeWaveFile = list.ToArray();
            string saveFile         = key + ".wav";

            File.WriteAllBytes(saveLocation + "\\" + saveFile, completeWaveFile);
        }
        /// <summary>
        /// Synthesis for a bubble.
        /// Based upon research by
        /// K. van den Doel, "Physically-based models for liquid sounds," in Proceedings of ICAD 04-Tenth Meeting of the International Conference on Auditory Display, 2004
        /// </summary>
        /// <param name="minRadius">The minimum radius of a water drop.</param>
        /// <param name="maxRadius">The maximum radius of a water drop.</param>
        /// <param name="frequencySampling">The sampling rate.</param>
        /// <param name="amount">The amount of water drops.</param>
        /// <returns></returns>
        static public double[,] WaterDrops(double minRadius, double maxRadius, uint frequencySampling, uint amount = 1)
        { //need to make it so the arrays can overlap each other. instead of uint amount have a param that contain the delays before the next bubble is created, out from the param figure out
          //their placement in the array
            System.Diagnostics.Debug.WriteLine("Water Drops " + System.Threading.Thread.CurrentThread.Name);
            double[] output = new double[0];
            for (int i = 0; i < amount; i++)
            {
                output = output.Concat(Waterdrop(minRadius, maxRadius, frequencySampling));
            }

            double maxValue = output.Max();
            double minValue = output.Min();

            for (int m = 0; m < output.Length; m++) //sounds like it is causing a little amount of clipping, save audio data and check it. Data does not indicate that
            {
                output[m] = 2 * ((output[m] - minValue) / (maxValue - minValue)) - 1;
            }

            double[,] multiChanAudio = new double[output.Length, 1];
            for (int i = 0; i < output.Length; i++)
            {
                multiChanAudio[i, 0] = output[i];
            }

            byte[] header = WaveHeaderToSignal(output.GetLength(0), frequencySampling, 1);
            double[,] audio = AudioStorageProcessing.AddWaveToSignal(multiChanAudio, header);
            return(audio);
        }
        /// <summary>
        /// Synthesises a marimba tone.
        /// Based upon research by...
        /// </summary>
        /// <param name="tilt">The hit location on the ???. 0.5 is in the middle, 1 and -1 are the edges.</param>
        /// <param name="velocity"></param>
        /// <param name="pressure">Controls how quickly the node decay.</param>
        /// <param name="frequency"></param>
        /// <param name="frequencySampling"></param>
        /// <returns></returns>
        static public double[,] Marimba(float tilt, float velocity, float pressure, uint frequency, uint frequencySampling)
        { //program it such that if a note is exceeding -1 1 that it get resized to not clip
            tilt = tilt < -1 ? -1 : tilt;
            tilt = tilt > 1 ? 1 : tilt;

            double[] mode =
            {
                0.12 * Math.Sin(1 * tilt * Math.PI),
                0.02 * Math.Sin(0.03 + 3.9 * tilt * Math.PI),
                0.03 * Math.Sin(0.5 + 9.3 * tilt * Math.PI)
            };
            double[] decay =
            {
                -0.0001 * pressure,
                -0.0001 * pressure,
                -0.0010 * pressure
            };

            double test  = 1;
            uint   index = 0;

            do
            {
                test = Math.Exp(decay[0] * index);
                index++;
            } while (test > 0.01);
            double[] time = new double[index - 1];
            for (int i = 0; i < time.Length; i++)
            {
                time[i] = i;
            }
            double[] note = new double[time.Length];

            for (int i = 0; i < note.Length; i++)
            {
                note[i] = velocity
                          * ((mode[0] * Math.Exp(decay[0] * time[i]) * Math.Sin(frequency * 2 * Math.PI / frequencySampling * time[i]))
                             + (mode[1] * Math.Exp(decay[1] * time[i]) * Math.Sin(frequency * 2 * 2 * Math.PI / frequencySampling * time[i]))
                             + (mode[2] * Math.Exp(decay[2] * time[i]) * Math.Sin(frequency * 3 * 2 * Math.PI / frequencySampling * time[i])));
            }

            double[,] multiChanAudio = new double[note.Length, 1];
            for (int i = 0; i < note.Length; i++)
            {
                multiChanAudio[i, 0] = note[i];
            }

            byte[] header = WaveHeaderToSignal(note.Length, frequencySampling, 1);
            double[,] audio = AudioStorageProcessing.AddWaveToSignal(multiChanAudio, header);
            return(audio);
        }
        static public double[,] WaterHittingResonSurf(uint samplingRate)
        {
            double[] output = new double[0];
            output = WaterHittingResonantSurface(samplingRate);
            double maxValue = output.Max();
            double minValue = output.Min();

            for (int m = 0; m < output.Length; m++) //sounds like it is causing a little amount of clipping, save audio data and check it. Data does not indicate it does
            {
                output[m] = 2 * ((output[m] - minValue) / (maxValue - minValue)) - 1;
            }

            double[,] multiChanAudio = new double[output.Length, 1];
            for (int i = 0; i < output.Length; i++)
            {
                multiChanAudio[i, 0] = output[i];
            }

            byte[] header = WaveHeaderToSignal(output.GetLength(0), samplingRate, 1);
            double[,] audio = AudioStorageProcessing.AddWaveToSignal(multiChanAudio, header);
            return(audio);
        }
Exemple #5
0
        public static void LoadAudio(string signalPathwayAndName)
        {
            byte[]   wav               = WaveClass.LoadAudioFile(signalPathwayAndName);
            string[] seperation        = signalPathwayAndName.Split("\\");
            string[] nameWithFormat    = seperation[seperation.Length - 1].Split(".");
            string   nameWithoutFormat = nameWithFormat[0];
            uint     headerSize        = 44;
            string   currentASCII      = "";
            uint     posistion         = 0;

            do
            {
                byte[] wordLooking =
                {
                    wav[posistion],
                    wav[posistion + 1],
                    wav[posistion + 2],
                    wav[posistion + 3]
                };
                currentASCII = Conversion.ByteArrayToASCII(wordLooking);
                posistion++;
            } while (currentASCII != "fmt ");
            uint fmtChunkStartLocation = --posistion;
            uint mainHeaderChunkSize   = fmtChunkStartLocation;

            byte[] sizeArray = new byte[4]
            {
                wav[fmtChunkStartLocation + 4],//+ 4 to placement because of ID chunk is 4 bytes
                wav[fmtChunkStartLocation + 5],
                wav[fmtChunkStartLocation + 6],
                wav[fmtChunkStartLocation + 7]
            };

            uint fmtChunkSize = 0;

            Conversion.ByteConverterToInterger(sizeArray, ref fmtChunkSize);
            sizeArray = new byte[2]
            {
                wav[fmtChunkStartLocation + 8],
                wav[fmtChunkStartLocation + 9]
            };
            fmtChunkSize += 8;
            uint fmtFormatCode = 0;

            Conversion.ByteConverterToInterger(sizeArray, ref fmtFormatCode);

            uint factChunkStartLocation = 0;
            uint factChuckSize          = 0;
            uint factNumberOfSamples;

            if (fmtFormatCode != 1)
            {
                currentASCII = "";
                posistion    = 8;
                do
                {
                    byte[] wordLooking =
                    {
                        wav[posistion],
                        wav[posistion + 1],
                        wav[posistion + 2],
                        wav[posistion + 3]
                    };
                    currentASCII = Conversion.ByteArrayToASCII(wordLooking);
                    posistion++;
                } while (currentASCII != "fact");
                factChunkStartLocation = --posistion;
            }

            currentASCII = "";
            posistion    = 8;
            do
            {
                byte[] wordLooking =
                {
                    wav[posistion],
                    wav[posistion + 1],
                    wav[posistion + 2],
                    wav[posistion + 3]
                };
                currentASCII = Conversion.ByteArrayToASCII(wordLooking);
                posistion++;
            } while (currentASCII != "data");
            uint dataChunkStartLocation = --posistion;

            headerSize = dataChunkStartLocation > factChunkStartLocation ? dataChunkStartLocation + 8 : factChunkStartLocation + factChuckSize;

            byte[] wavHeader = new byte[headerSize];
            for (int i = 0; i < headerSize; i++)
            {
                wavHeader[i] = wav[i];
            }
            ushort channelAmount   = WaveClass.ChannelAmount(wavHeader, fmtChunkStartLocation);
            uint   dataSegmentSize = WaveClass.DataSectionSize(wavHeader, dataChunkStartLocation);
            short  bitsPerSample   = WaveClass.BitsPerSample(wavHeader, fmtChunkStartLocation);

            double[,] audioScaled     = WaveClass.ByteArrayToTimeDomain(wav, dataSegmentSize, channelAmount, bitsPerSample, (ulong)wavHeader.Length);
            double[,] audioWithHeader = AudioStorageProcessing.AddWaveToSignal(audioScaled, wavHeader);
            Storage.SignalToStorage(audioWithHeader, nameWithoutFormat);
        }