Пример #1
0
        public WaveOutBuffer(IntPtr waveOutHandle, int bufferSize, IntPtr userData)
        {
            if (waveOutHandle == IntPtr.Zero)
            {
                throw new ArgumentNullException("waveOutHandle");
            }
            if (bufferSize <= 0)
            {
                throw new ArgumentOutOfRangeException("bufferSize");
            }

            _waveOutHandle = waveOutHandle;

            _buffer       = new byte[bufferSize];
            _bufferHandle = GCHandle.Alloc(_buffer, GCHandleType.Pinned);

            _waveHeader = new WaveHeader()
            {
                bufferLength = bufferSize,
                dataBuffer   = _bufferHandle.AddrOfPinnedObject(),
                loops        = 1,
                userData     = userData
            };
            _waveHeaderHandle = GCHandle.Alloc(_waveHeaderHandle, GCHandleType.Pinned); //do we really need the waveheaderhandle?
        }
    public SoundGenerator(List <SoundFragment> sound)
    {
        header = new WaveHeader();
        format = new WaveFormatChunk();
        data   = new WaveDataChunk();

        int numberOfSamples = sound.Sum(x => (int)(format.dwSamplesPerSec * format.wChannels * x.Duration));

        data.shortArray = new short[numberOfSamples];

        int amplitude = 32760;
        int counter   = 0;

        foreach (SoundFragment fragment in sound)
        {
            double t = (Math.PI * 2 * fragment.Frequency) / (format.dwSamplesPerSec * format.wChannels);
            uint   sampleCountForFragment = (uint)(format.dwSamplesPerSec * format.wChannels * fragment.Duration);
            for (uint i = 0; i < sampleCountForFragment - 1; i++)
            {
                for (int channel = 0; channel < format.wChannels; channel++)
                {
                    data.shortArray[counter + channel] = Convert.ToInt16(amplitude * Math.Sin(t * i));
                }

                counter++;
            }
        }

        data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8));
    }
Пример #3
0
        public unsafe static void Save(Song song, string filename, int sampleRate, int loopCount, int duration, int channelMask)
        {
            var project = song.Project;
            var player  = new WavPlayer(sampleRate, loopCount, channelMask);
            var samples = player.GetSongSamples(song, project.PalMode, duration);

            using (var file = new FileStream(filename, FileMode.Create))
            {
                var header = new WaveHeader();

                // RIFF WAVE Header
                header.chunkId[0] = (byte)'R';
                header.chunkId[1] = (byte)'I';
                header.chunkId[2] = (byte)'F';
                header.chunkId[3] = (byte)'F';
                header.format[0]  = (byte)'W';
                header.format[1]  = (byte)'A';
                header.format[2]  = (byte)'V';
                header.format[3]  = (byte)'E';

                // Format subchunk
                header.subChunk1Id[0] = (byte)'f';
                header.subChunk1Id[1] = (byte)'m';
                header.subChunk1Id[2] = (byte)'t';
                header.subChunk1Id[3] = (byte)' ';
                header.audioFormat    = 1;          // FOR PCM
                header.numChannels    = 1;          // 1 for MONO, 2 for stereo
                header.sampleRate     = sampleRate; // ie 44100 hertz, cd quality audio
                header.bitsPerSample  = 16;         //
                header.byteRate       = header.sampleRate * header.numChannels * header.bitsPerSample / 8;
                header.blockAlign     = (short)(header.numChannels * header.bitsPerSample / 8);

                // Data subchunk
                header.subChunk2Id[0] = (byte)'d';
                header.subChunk2Id[1] = (byte)'a';
                header.subChunk2Id[2] = (byte)'t';
                header.subChunk2Id[3] = (byte)'a';

                // All sizes for later:
                // chuckSize = 4 + (8 + subChunk1Size) + (8 + subChubk2Size)
                // subChunk1Size is constanst, i'm using 16 and staying with PCM
                // subChunk2Size = nSamples * nChannels * bitsPerSample/8
                // Whenever a sample is added:
                //    chunkSize += (nChannels * bitsPerSample/8)
                //    subChunk2Size += (nChannels * bitsPerSample/8)
                header.subChunk1Size = 16;
                header.subChunk2Size = samples.Length * sizeof(short);
                header.chunkSize     = 4 + (8 + header.subChunk1Size) + (8 + header.subChunk2Size);

                var headerBytes = new byte[sizeof(WaveHeader)];
                Marshal.Copy(new IntPtr(&header), headerBytes, 0, headerBytes.Length);
                file.Write(headerBytes, 0, headerBytes.Length);

                // So lame.
                foreach (var s in samples)
                {
                    file.Write(BitConverter.GetBytes(s), 0, sizeof(short));
                }
            }
        }
Пример #4
0
        public WaveGenerator(List <Note> notes, float volume)
        {
            // Init chunks
            header = new WaveHeader();
            format = new WaveFormatChunk();
            data   = new WaveDataChunk();

            var  milliseconds = notes.Select((x) => x.Duration.TotalMilliseconds).Sum();
            uint numSamples   = (uint)(((format.dwSamplesPerSec * milliseconds) / 1000));
            int  amplitude    = 32760; // Max amplitude for 16-bit audio
            uint sampleCount  = 0;     // used as a "cursor" in the next Foreach

            // Initialize the 16-bit array and Calculate the repsective values
            data.shortArray = new short[numSamples];
            foreach (var n in notes)
            {
                // the time-steps the sine wave takes (period [2 pi f]) divided by the steps per period
                double t = (Math.PI * 2 * n.Frequency) / format.dwSamplesPerSec;

                // Calculate the amount of samples you will use for said Note
                var samplesThisNote = format.dwSamplesPerSec * n.Duration.TotalSeconds;

                // Loop over sampleCount as said before (it acts as u cursor)
                for (uint i = sampleCount; i < (samplesThisNote + sampleCount) - 1; i++)
                {
                    data.shortArray[i] = Convert.ToInt16(amplitude * Math.Sin(t * i) * volume);
                }
                sampleCount += (uint)samplesThisNote;
            }

            // Calculate data chunk size in bytes
            data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8));
        }
Пример #5
0
        /// <summary>
        /// Called when we get a new buffer of recorded data
        /// </summary>
        private void Callback(IntPtr waveInHandle, WaveInterop.WaveMessage message, IntPtr userData,
                              WaveHeader waveHeader, IntPtr reserved)
        {
            if (message == WaveInterop.WaveMessage.WaveInData)
            {
                if (recording)
                {
                    var hBuffer = (GCHandle)waveHeader.userData;
                    var buffer  = (WaveInBuffer)hBuffer.Target;
                    if (buffer == null)
                    {
                        return;
                    }

                    lastReturnedBufferIndex = Array.IndexOf(buffers, buffer);
                    RaiseDataAvailable(buffer);
                    try
                    {
                        buffer.Reuse();
                    }
                    catch (Exception e)
                    {
                        recording = false;
                        RaiseRecordingStopped(e);
                    }
                }
            }
        }
    double freq   = 220.0f; // Concert A: 440Hz

    public WaveGenerator()
    {
        // Init chunks
        header = new WaveHeader();
        format = new WaveFormatChunk();
        data   = new WaveDataChunk();
    }
Пример #7
0
        public void StopRecord()
        {
            RecordData recordData = StopRec();

            bData = new byte[recordData.len];
            Debug.WriteLine(recordData.len);
            Marshal.Copy(recordData.ip, bData, 0, (int)recordData.len);

            WaveHeader header = (WaveHeader)Marshal.PtrToStructure(GetWaveform(), typeof(WaveHeader));

            wav = new Wav("RIFF", recordData.len + 36, "WAVE",
                          "fmt", 16, 1, header.nChannels, header.nSamplesPerSec,
                          header.nAvgBytesPerSec, header.nBlockAlign, header.wBitsPerSample,
                          "data", recordData.len);


            short[] temp = new short[recordData.len / (int)wav.blockAlign];
            for (int i = 0; i < temp.Length - 1; i++)
            {
                temp[i] = BitConverter.ToInt16(bData, i * (int)wav.blockAlign);
            }
            samples = temp.Select(x => (double)(x)).ToArray();

            plotSample(samples.Length);
        }
Пример #8
0
        public void SaveAsWaveFile(string fileName, IEnumerable <SpeechPart> audioData)
        {
            int dataLength = 0;

            foreach (SpeechPart item in audioData)
            {
                dataLength += item.RawAudio.Length;
            }

            byte[] headerByte = new WaveHeader(
                1,     //单声道
                16000, //采样频率
                16,    //每个采样8bit
                dataLength).ToBytes();

            using (FileStream stream = File.Create(fileName))
            {
                //写入文件头
                stream.Write(headerByte, 0, headerByte.Length);
                foreach (SpeechPart item in audioData)
                {
                    stream.Write(item.RawAudio, 0, item.RawAudio.Length);
                }

                stream.Flush();
                stream.Close();
            }
        }
Пример #9
0
        public static void PlayTone(Tone[] tones)
        {
            WAVEFORMAT_MIDI wfm = new WAVEFORMAT_MIDI();

            wfm.WAVEFORMATEX.FormatTag  = FormatTag.MIDI;
            wfm.WAVEFORMATEX.Channels   = 1;
            wfm.WAVEFORMATEX.BlockAlign = 8; // sizeof(WAVEFORMAT_MIDI_MESSAGE);
            wfm.WAVEFORMATEX.Size       = WAVEFORMAT_MIDI_EXTRASIZE;

            // trial & error seems to be the way to get this - tested using an Axim x51
            // maybe expose these if it varies from hardware to hardware
            wfm.USecPerQuarterNote  = 100000;
            wfm.TicksPerQuarterNote = 15;

            IntPtr          hWaveOut;
            EventWaitHandle hEvent = new EventWaitHandle(false, EventResetMode.ManualReset);

            byte[] d = wfm.GetBytes();

            int result = WaveAudio.NativeMethods.waveOutOpen(out hWaveOut, 0, d, hEvent.Handle, 0, CALLBACK_EVENT);

            Audio.CheckWaveError(result);

            WAVEFORMAT_MIDI_MESSAGE[] messages = new WAVEFORMAT_MIDI_MESSAGE[2 * tones.Length];
            int totalDuration = 0;

            for (int i = 0; i < tones.Length; i++)
            {
                messages[i * 2].DeltaTicks     = 0;
                messages[i * 2].MidiMsg        = (uint)(0x7F0090 | (tones[i].MIDINote << 8)); // Note on
                messages[i * 2 + 1].DeltaTicks = (uint)(tones[i].Duration);
                messages[i * 2 + 1].MidiMsg    = (uint)(0x7F0080 | (tones[i].MIDINote << 8)); // Note off

                totalDuration += tones[i].Duration;
            }

            byte[] headerData = new byte[messages.Length * WAVEFORMAT_MIDI_MESSAGE.Length];
            for (int i = 0; i < messages.Length; i++)
            {
                Buffer.BlockCopy(messages[i].GetBytes(), 0, headerData, i * WAVEFORMAT_MIDI_MESSAGE.Length, WAVEFORMAT_MIDI_MESSAGE.Length);
            }
            WaveHeader header = new WaveHeader(headerData);

            result = WaveAudio.NativeMethods.waveOutPrepareHeader(hWaveOut, header.Pointer, header.HeaderLength);
            Audio.CheckWaveError(result);

            result = WaveAudio.NativeMethods.waveOutWrite(hWaveOut, header.Pointer, header.HeaderLength);
            Audio.CheckWaveError(result);

            if (!hEvent.WaitOne(totalDuration * 20, false))
            {
                Debugger.Break();
            }

            result = WaveAudio.NativeMethods.waveOutUnprepareHeader(hWaveOut, header.Pointer, header.HeaderLength);
            Audio.CheckWaveError(result);

            result = WaveAudio.NativeMethods.waveOutClose(hWaveOut);
            Audio.CheckWaveError(result);
        }
Пример #10
0
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                //dispose managed
            }

            if (_header != null)
            {
                try
                {
                    Unprepare();
                }
                catch (Exception) { }
                finally
                {
                    _header = null;
                }
            }

            if (_bufferHandle.IsAllocated)
            {
                _bufferHandle.Free();
            }
            if (_headerHandle.IsAllocated)
            {
                _headerHandle.Free();
            }
            if (_userDataHandle.IsAllocated)
            {
                _userDataHandle.Free();
            }
        }
        public fileSaver(WaveHeader header, WaveFormatChunk format, WaveDataChunk data, string filePath)
        {
            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                using (var writer = new BinaryWriter(fileStream))
                {
                    // Write the header
                    writer.Write(header.sGroupID.ToCharArray());
                    writer.Write(header.dwFileLength);
                    writer.Write(header.sRiffType.ToCharArray());

                    // Write the format chunk
                    writer.Write(format.sChunkID.ToCharArray());
                    writer.Write(format.dwChunkSize);
                    writer.Write(format.wFormatTag);
                    writer.Write(format.wChannels);
                    writer.Write(format.dwSamplesPerSec);
                    writer.Write(format.dwAvgBytesPerSec);
                    writer.Write(format.wBlockAlign);
                    writer.Write(format.wBitsPerSample);

                    // Write the data chunk
                    writer.Write(data.sChunkID.ToCharArray());
                    writer.Write(data.dwChunkSize);
                    foreach (short dataPoint in data.shortArray)
                    {
                        writer.Write(dataPoint);
                    }

                    // Jump back to Header.FileLength and calculate the TOTAL filesize
                    writer.Seek(4, SeekOrigin.Begin);
                    writer.Write((uint)writer.BaseStream.Length - 8); // Header parts are ignore (-8)
                }
            }
        }
Пример #12
0
        protected override void WndProc(ref Message m)
        {
            var message = (WaveInterop.WaveMessage)m.Msg;

            switch (message)
            {
            case WaveInterop.WaveMessage.WaveOutDone:
            case WaveInterop.WaveMessage.WaveInData:
                var hOutputDevice = m.WParam;
                var waveHeader    = new WaveHeader();
                Marshal.PtrToStructure(m.LParam, waveHeader);
                _waveCallback(hOutputDevice, message, IntPtr.Zero, waveHeader, IntPtr.Zero);
                break;

            case WaveInterop.WaveMessage.WaveOutOpen:
            case WaveInterop.WaveMessage.WaveOutClose:
            case WaveInterop.WaveMessage.WaveInClose:
            case WaveInterop.WaveMessage.WaveInOpen:
                _waveCallback(m.WParam, message, IntPtr.Zero, null, IntPtr.Zero);
                break;

            default:
                base.WndProc(ref m);
                break;
            }
        }
Пример #13
0
	public void Write (float[] clipData, WaveFormatChunk format, FileStream stream)
	{
		WaveHeader header = new WaveHeader ();
		WaveDataChunk data = new WaveDataChunk ();
		
		data.shortArray = new short[clipData.Length];
		for (int i = 0; i < clipData.Length; i++)
			data.shortArray [i] = (short)(clipData [i] * 32767);
		
		data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8));
		
		BinaryWriter writer = new BinaryWriter (stream);
		writer.Write (header.sGroupID.ToCharArray ());
		writer.Write (header.dwFileLength);
		writer.Write (header.sRiffType.ToCharArray ());
		writer.Write (format.sChunkID.ToCharArray ());
		writer.Write (format.dwChunkSize);
		writer.Write (format.wFormatTag);
		writer.Write (format.wChannels);
		writer.Write (format.dwSamplesPerSec);
		writer.Write (format.dwAvgBytesPerSec);
		writer.Write (format.wBlockAlign);
		writer.Write (format.wBitsPerSample);
		writer.Write (data.sChunkID.ToCharArray ());
		writer.Write (data.dwChunkSize);
		foreach (short dataPoint in data.shortArray) {
			writer.Write (dataPoint);
		}
		writer.Seek (4, SeekOrigin.Begin);
		uint filesize = (uint)writer.BaseStream.Length;
		writer.Write (filesize - 8);
		writer.Close ();
	}
Пример #14
0
 public static WaveHeader ReadWaveHeader(Stream stream)
 {
     if (stream == null)
     {
         return((WaveHeader)null);
     }
     using (BinaryReader reader = new BinaryReader(stream))
         return(WaveHeader.ReadWaveHeader(reader));
 }
Пример #15
0
        public void BeginRecording()
        {
            waveHeader             = new WaveHeader();
            formatChunk            = new FormatChunk(SampleRate, NumChannels);
            dataChunk              = new DataChunk();
            waveHeader.FileLength += formatChunk.Length();

            IsRecording = true;

            onScreenDisplayHandler.EnqueueMessage("Sound recording started.");
        }
Пример #16
0
    public static WaveHeader ReadWaveHeader(BinaryReader reader)
    {
        WaveHeader waveHeader = new WaveHeader();

        waveHeader.RIFF = Encoding.ASCII.GetString(reader.ReadBytes(4));
        waveHeader.Size = reader.ReadInt32();
        waveHeader.WAVE = Encoding.ASCII.GetString(reader.ReadBytes(4));
        if (waveHeader.RIFF.ToUpper() != "RIFF" || waveHeader.WAVE.ToUpper() != "WAVE")
        {
            return((WaveHeader)null);
        }
        while (waveHeader.FMT == null || waveHeader.FMT.ToLower() != "fmt")
        {
            waveHeader.FMT = Encoding.ASCII.GetString(reader.ReadBytes(4));
            if (!(waveHeader.FMT.ToLower().Trim() == "fmt"))
            {
                uint num = reader.ReadUInt32();
                reader.BaseStream.Seek((long)num, SeekOrigin.Current);
            }
            else
            {
                break;
            }
        }
        waveHeader.FmtChunkSize = reader.ReadInt32();
        waveHeader.FormatId     = reader.ReadInt16();
        waveHeader.Channels     = reader.ReadInt16();
        waveHeader.Frequency    = reader.ReadInt32();
        waveHeader.DataSpeed    = reader.ReadInt32();
        waveHeader.BlockSize    = reader.ReadInt16();
        waveHeader.BitPerSample = reader.ReadInt16();
        reader.BaseStream.Seek((long)(waveHeader.FmtChunkSize - 16), SeekOrigin.Current);
        while (waveHeader.DATA == null || waveHeader.DATA.ToLower() != "data")
        {
            waveHeader.DATA = Encoding.ASCII.GetString(reader.ReadBytes(4));
            if (!(waveHeader.DATA.ToLower() == "data"))
            {
                uint num = reader.ReadUInt32();
                reader.BaseStream.Seek((long)num, SeekOrigin.Current);
            }
            else
            {
                break;
            }
        }
        waveHeader.TrueWavBufSize  = reader.ReadInt32();
        waveHeader.TrueSamples     = waveHeader.TrueWavBufSize / ((int)waveHeader.BitPerSample / 8) / (int)waveHeader.Channels;
        waveHeader.TrueWavBufIndex = (int)reader.BaseStream.Position;
        reader.BaseStream.Seek(0L, SeekOrigin.Begin);
        return(waveHeader);
    }
Пример #17
0
        public void Initialize()
        {
            _buffer = new byte[_bufferSize];
            _header = new WaveHeader();

            _headerHandle   = GCHandle.Alloc(_header, GCHandleType.Pinned);
            _bufferHandle   = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
            _userDataHandle = GCHandle.Alloc(this);

            _header.bufferLength = _bufferSize;
            _header.dataBuffer   = _bufferHandle.AddrOfPinnedObject();
            _header.loops        = 1;
            _header.userData     = (IntPtr)_userDataHandle;

            Prepare();
            AddBuffer();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DialogAudioOutputStream"/> class.
        /// </summary>
        /// <param name="format"> The audio format of the underlying data. </param>
        protected DialogAudioOutputStream(DialogAudio format)
            : this()
        {
            Contract.Requires(format != null);
            Contract.Requires(this.bufferStream.Position == 0);

            this.Format = format;
            var encoding = this.Format.Encoding;

            // For PCM streams, we will assume that there's no header information available and write what's needed
            // for playback.
            if (encoding.Subtype == "WAV" || encoding.Subtype == "PCM")
            {
                WaveHeader.WriteWaveFormatHeaderToStream(this.bufferStream, encoding, WaveHeaderLengthOption.UseMaximumLength);
                this.bufferStream.Seek(0, SeekOrigin.Begin);
            }
        }
Пример #19
0
        /// <summary>
        /// creates a new wavebuffer
        /// </summary>
        /// <param name="waveInHandle">WaveIn device to write to</param>
        /// <param name="bufferSize">Buffer size in bytes</param>
        public WaveInBuffer(IntPtr waveInHandle, Int32 bufferSize)
        {
            this.bufferSize   = bufferSize;
            buffer            = new byte[bufferSize];
            hBuffer           = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            this.waveInHandle = waveInHandle;

            header              = new WaveHeader();
            hHeader             = GCHandle.Alloc(header);
            header.dataBuffer   = hBuffer.AddrOfPinnedObject();
            header.bufferLength = bufferSize;
            header.loops        = 1;
            hThis           = GCHandle.Alloc(this);
            header.userData = (IntPtr)hThis;

            MmException.Try(WaveInterop.waveInPrepareHeader(waveInHandle, header, Marshal.SizeOf(header)), "waveInPrepareHeader");
            MmException.Try(WaveInterop.waveInAddBuffer(waveInHandle, header, Marshal.SizeOf(header)), "waveInAddBuffer");
        }
Пример #20
0
        protected virtual void Callback(IntPtr handle, WaveMsg msg, UIntPtr user, WaveHeader header, UIntPtr reserved)
        {
            if (_hWaveOut != handle)
            {
                return; //message does not belong to this waveout instance
            }
            if (msg == WaveMsg.WOM_DONE)
            {
                GCHandle      hBuffer = (GCHandle)header.userData;
                WaveOutBuffer buffer  = hBuffer.Target as WaveOutBuffer;
                System.Threading.Interlocked.Decrement(ref _activeBuffers);

                if (buffer == null)
                {
                    return;
                }
                if (_playbackState != SoundOut.PlaybackState.Stopped)
                {
                    lock (_lockObj)
                    {
                        if (buffer.WriteData())
                        {
                            System.Threading.Interlocked.Increment(ref _activeBuffers);
                        }
                    }
                }

                if (_activeBuffers == 0)
                {
                    _playbackState = SoundOut.PlaybackState.Stopped;
                    RaiseStopped();
                }
            }
            else if (msg == WaveMsg.WOM_CLOSE)
            {
                var state = _playbackState;
                _playbackState = SoundOut.PlaybackState.Stopped;
                if (state != SoundOut.PlaybackState.Stopped)
                {
                    RaiseStopped();
                }
                Debug.WriteLine("WaveOut::Callback: Closing WaveOut.");
            }
        }
Пример #21
0
 WaveHeader GetWaveHeader(int dataLen)
 {
     WaveHeader header = new WaveHeader()
     {
         riffID=0x46464952,
         fileSize=dataLen+36,
         riffType=0x45564157,
         fmtID=0x20746D66,
         fmtSize=16,
         fmtTag=0x0001,
         fmtChannel=1,
         fmtSamplesPerSec=16000,
         avgBytesPerSec=32000,
         blockAlign=2,
         BitsPerSameple=16,
         dataID=0x61746164,
         dataSize=dataLen
     };
     return header;
 }
Пример #22
0
        private GCHandle _hThis;   // for the user callback

        /// <summary>
        /// creates a new wavebuffer
        /// </summary>
        /// <param name="hWaveOut">WaveOut device to write to</param>
        /// <param name="bufferSize">Buffer size in bytes</param>
        /// <param name="bufferFillStream">Stream to provide more data</param>
        /// <param name="waveOutLock">Lock to protect WaveOut API's from being called on >1 thread</param>
        public WaveOutBuffer(IntPtr hWaveOut, int bufferSize, IWaveProvider bufferFillStream, object waveOutLock)
        {
            BufferSize   = bufferSize;
            _buffer      = new byte[bufferSize];
            _hBuffer     = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
            _hWaveOut    = hWaveOut;
            _waveStream  = bufferFillStream;
            _waveOutLock = waveOutLock;

            _header              = new WaveHeader();
            _hHeader             = GCHandle.Alloc(_header, GCHandleType.Pinned);
            _header.dataBuffer   = _hBuffer.AddrOfPinnedObject();
            _header.bufferLength = bufferSize;
            _header.loops        = 1;
            _hThis           = GCHandle.Alloc(this);
            _header.userData = (IntPtr)_hThis;
            lock (waveOutLock)
            {
                MmException.Try(WaveInterop.waveOutPrepareHeader(hWaveOut, _header, Marshal.SizeOf(_header)), "waveOutPrepareHeader");
            }
        }
Пример #23
0
        /// <summary>
        /// creates a new wavebuffer
        /// </summary>
        /// <param name="hWaveOut">WaveOut device to write to</param>
        /// <param name="bufferSize">Buffer size in bytes</param>
        /// <param name="bufferFillStream">Stream to provide more data</param>
        /// <param name="waveOutLock">Lock to protect WaveOut API's from being called on >1 thread</param>
        public WaveOutBuffer(IntPtr hWaveOut, Int32 bufferSize, IWaveProvider bufferFillStream, object waveOutLock)
        {
            this.bufferSize  = bufferSize;
            buffer           = new byte[bufferSize];
            hBuffer          = GCHandle.Alloc(buffer, GCHandleType.Pinned);
            this.hWaveOut    = hWaveOut;
            waveStream       = bufferFillStream;
            this.waveOutLock = waveOutLock;

            header              = new WaveHeader();
            hHeader             = GCHandle.Alloc(header);
            header.dataBuffer   = hBuffer.AddrOfPinnedObject();
            header.bufferLength = bufferSize;
            header.loops        = 1;
            hThis           = GCHandle.Alloc(this);
            header.userData = (IntPtr)hThis;
            lock (waveOutLock)
            {
                MmException.Try(WaveInterop.waveOutPrepareHeader(hWaveOut, header, Marshal.SizeOf(header)), "waveOutPrepareHeader");
            }
        }
Пример #24
0
        public WaveGenerator(WaveExampleType type)
        {
            // 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;

                    // Initialize the 16-bit array
                    data.shortArray = new short[numSamples];

                    int amplitude = 32760;  // Max amplitude for 16-bit audio
                    double freq = 440.0f;   // Concert A: 440Hz

                    // 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;
            }
        }
Пример #25
0
        /// <summary>
        /// 根据数据段的长度,生产文件头
        /// </summary>
        /// <param name="dataLen">音频数据长度</param>
        /// <returns>返回wav文件头结构体</returns>
        WaveHeader getWave_Header(int dataLen)
        {
            var wavHeader = new WaveHeader();

            wavHeader.RiffID   = 0x46464952;         //字符RIFF
            wavHeader.FileSize = dataLen + 36;
            wavHeader.RiffType = 0x45564157;         //字符WAVE

            wavHeader.FmtID            = 0x20746D66; //字符fmt
            wavHeader.FmtSize          = 16;
            wavHeader.FmtTag           = 0x0001;
            wavHeader.FmtChannel       = 1;       //单声道
            wavHeader.FmtSamplesPerSec = 16000;   //采样频率
            wavHeader.AvgBytesPerSec   = 32000;   //每秒所需字节数
            wavHeader.BlockAlign       = 2;       //每个采样1个字节
            wavHeader.BitsPerSample    = 16;      //每个采样8bit

            wavHeader.DataID   = 0x61746164;      //字符data
            wavHeader.DataSize = dataLen;

            return(wavHeader);
        }
Пример #26
0
    public void Write(float[] clipData, WaveFormatChunk format, FileStream stream)
    {
        WaveHeader    header = new WaveHeader();
        WaveDataChunk data   = new WaveDataChunk();

        data.shortArray = new short[clipData.Length];
        for (int i = 0; i < clipData.Length; i++)
        {
            data.shortArray [i] = (short)(clipData [i] * 32767);
        }

        data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8));

        BinaryWriter writer = new BinaryWriter(stream);

        writer.Write(header.sGroupID.ToCharArray());
        writer.Write(header.dwFileLength);
        writer.Write(header.sRiffType.ToCharArray());
        writer.Write(format.sChunkID.ToCharArray());
        writer.Write(format.dwChunkSize);
        writer.Write(format.wFormatTag);
        writer.Write(format.wChannels);
        writer.Write(format.dwSamplesPerSec);
        writer.Write(format.dwAvgBytesPerSec);
        writer.Write(format.wBlockAlign);
        writer.Write(format.wBitsPerSample);
        writer.Write(data.sChunkID.ToCharArray());
        writer.Write(data.dwChunkSize);
        foreach (short dataPoint in data.shortArray)
        {
            writer.Write(dataPoint);
        }
        writer.Seek(4, SeekOrigin.Begin);
        uint filesize = (uint)writer.BaseStream.Length;

        writer.Write(filesize - 8);
        writer.Close();
    }
    public static AudioClip Load(
        string path,
        long SongLength,
        uAudio.uAudio_backend.uAudio uAudio,
        ref string szErrorMs)
    {
        string extension = Path.GetExtension(path);

        if (extension == ".wav" || extension == ".WAV")
        {
            WaveHeader waveHeader    = WaveHeader.ReadWaveHeader(path);
            float[]    rangedRawData = ExternalAudioClip.CreateRangedRawData(path, waveHeader.TrueWavBufIndex, waveHeader.TrueSamples, (int)waveHeader.Channels, (int)waveHeader.BitPerSample);
            return(rangedRawData.Length == 0 ? (AudioClip)null : ExternalAudioClip.CreateClip(Path.GetFileNameWithoutExtension(path), rangedRawData, waveHeader.TrueSamples, (int)waveHeader.Channels, waveHeader.Frequency));
        }
        if (!(extension == ".mp3") && !(extension == ".MP3"))
        {
            return((AudioClip)null);
        }
        mp3AudioClip._uAudio = uAudio;
        AudioClip audioClip = mp3AudioClip.LoadMp3(path, SongLength);

        szErrorMs = mp3AudioClip.szErrorMs;
        return(audioClip);
    }
Пример #28
0
            public WaveGenerator(List <short> Data)
            {
                header = new WaveHeader();
                format = new WaveFormatChunk();
                data   = new WaveDataChunk();

                int numSamples = Data.Count;

                data.shortArray = new short[numSamples];

                for (int i = 0; i < numSamples; i++)
                {
                    data.shortArray[i] = Data[i];
                }

                data.dwChunkSize = (uint)(data.shortArray.Length * (format.wBitsPerSample / 8));
                TimeSpan TS = new TimeSpan(0, 0, (int)((float)numSamples / (float)format.dwSamplesPerSec));

                if (Verbose)
                {
                    Console.WriteLine("");
                }
                Console.WriteLine("wave generated: {0} seconds: {1}", (float)numSamples / (float)format.dwSamplesPerSec, TS.ToString());
            }
Пример #29
0
 protected virtual void Callback(IntPtr handle, WaveMsg msg, UIntPtr user, WaveHeader header, UIntPtr reserved)
 {
     if (msg == WaveMsg.WIM_DATA)
     {
         if (!stopped)
         {
             var buffer = ((GCHandle)header.userData).Target as WaveInBuffer;
             RaiseDataAvailable(buffer);
             try
             {
                 buffer.Reset();
             }
             catch (MmException)
             {
                 stopped = true;
                 RaiseStopped();
             }
         }
     }
     else if (msg == WaveMsg.WIM_CLOSE)
     {
         RaiseStopped();
     }
 }
Пример #30
0
        /// <summary>
        /// Main program.
        /// </summary>
        /// <param name="args"></param>
        private void Run(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine(
            @"{0} [options ...] <path to MIDI.mid>

            Description:
            Clicker generates a WAVE file click track given a MIDI sequence with meter/key
            and tempo change messages. The click track serves as a solid, sample-accurate
            metronome that will line up with the MIDI sequence. You can import the
            generated click track into any MIDI-friendly DAW tool such as SONAR, Cubase,
            etc. to record with. You can even share the click track with other recording
            artists working on your project to serve as a timebase to help synchronize work
            across distances.

            Author:     James S. Dunne http://bittwiddlers.org/
            Copyright:  2011, bittwiddlers.org
            Source:     http://github.com/JamesDunne/clicker

            Options:
            -s <samplerate>      Set the output WAVE file's sample rate in Hz
                         (default 48000 Hz)
            -c <channels>        Set the output WAVE file's number of channels
                         (1 or 2, default 2)
            -d <click division>  Set the metronome to click on each (2^N)th note,
                         scaling meter signatures appropriately to match.
                         (default: off, click on meter beats only)
            -ao                  Attenuate meter's off-beats if meter is faster
                         than the metronome. (default: off)
            -ad                  Attenuate inserted beats if metronome is clicking
                         faster than the meter. (default: off)
            <path to MIDI.mid>   Path to the MIDI arrangement to generate the click
                         track for.

            Outputs:
            <path to MIDI.mid>.click.wav
            ", Process.GetCurrentProcess().ProcessName);
                return;
            }

            bool early = false;
            Queue<string> aq = new Queue<string>(args);
            while (!early && (aq.Count > 0))
            {
                string arg = aq.Peek();

                switch (arg.ToLower())
                {
                    case "-s":
                        aq.Dequeue();
                        if (!Int32.TryParse(aq.Dequeue(), out samplesPerSec))
                            samplesPerSec = 48000;
                        break;
                    case "-c":
                        aq.Dequeue();
                        if (!Int32.TryParse(aq.Dequeue(), out channels))
                            channels = 1;
                        break;
                    case "-d":
                        aq.Dequeue();
                        if (Int32.TryParse(aq.Dequeue(), out clickOnDivision))
                            forceClickDivision = true;
                        break;
                    case "-ao":
                        aq.Dequeue();
                        attenuateProperOffBeats = true;
                        break;
                    case "-ad":
                        aq.Dequeue();
                        attenuateDividedBeats = true;
                        break;
                    default:
                        early = true;
                        break;
                }
            }

            if (aq.Count < 1)
            {
                Console.WriteLine("Expected path to MIDI sequence.");
                return;
            }

            FileInfo midiFile = new FileInfo(aq.Dequeue());
            if (!midiFile.Exists)
            {
                Console.WriteLine("Could not find path '{0}'.", midiFile.FullName);
                return;
            }

            // Load the MIDI sequence:
            Sequence seq = new Sequence(midiFile.FullName);

            // Load our clicks (stereo 16-bit clips):
            var asm = System.Reflection.Assembly.GetExecutingAssembly();
            #if true
            byte[] pinghiraw = getAllBytes(asm.GetManifestResourceStream("Clicker.pinghi48k16b.raw"));
            #else
            byte[] pinghiraw = File.ReadAllBytes("pinghi48k16b.raw");
            #endif
            short[,] pinghi = new short[pinghiraw.Length / 4, 2];
            for (int i = 0, b = 0; i < pinghiraw.Length - 4; i += 4, ++b)
            {
                pinghi[b, 0] = unchecked((short)(pinghiraw[i + 0] | (pinghiraw[i + 1] << 8)));
                pinghi[b, 1] = unchecked((short)(pinghiraw[i + 2] | (pinghiraw[i + 3] << 8)));
            }
            int pinghiLength = pinghi.GetUpperBound(0) + 1;

            #if true
            byte[] pingloraw = getAllBytes(asm.GetManifestResourceStream("Clicker.pinglo48k16b.raw"));
            #else
            byte[] pingloraw = File.ReadAllBytes("pinglo48k16b.raw");
            #endif
            short[,] pinglo = new short[pingloraw.Length / 4, 2];
            for (int i = 0, b = 0; i < pingloraw.Length - 4; i += 4, ++b)
            {
                pinglo[b, 0] = unchecked((short)(pingloraw[i + 0] | (pingloraw[i + 1] << 8)));
                pinglo[b, 1] = unchecked((short)(pingloraw[i + 2] | (pingloraw[i + 3] << 8)));
            }
            int pingloLength = pinglo.GetUpperBound(0) + 1;

            // Grab meter and tempo changes from any track:
            var timeChanges =
                from tr in seq
                from ev in tr.Iterator()
                where ev.MidiMessage.MessageType == MessageType.Meta
                let mm = (MetaMessage)ev.MidiMessage
                where mm.MetaType == MetaType.TimeSignature || mm.MetaType == MetaType.Tempo
                orderby ev.AbsoluteTicks ascending
                select new { ev, mm };

            var lastEvent = (
                from tr in seq
                from ev in tr.Iterator()
                orderby ev.AbsoluteTicks ascending
                select ev
            ).Last();

            // Create a default tempo of 120 bpm (500,000 us/b):
            var tcb = new TempoChangeBuilder() { Tempo = 500000 };
            tcb.Build();
            currentTempo = new TempoMessage(tcb.Result);

            // Create a default time signature of 4/4:
            var tsb = new TimeSignatureBuilder() { Numerator = 4, Denominator = 4 };
            tsb.Build();
            currentTimeSignature = new TimeSignatureMessage(tsb.Result);

            ticksPerQuarter = seq.Division;
            calcUsecPerTick();
            calcBeatTicks();

            double sample = 0d;

            samplesPerUsec = (double)samplesPerSec / 1000000d;

            string outWaveFile = Path.Combine(midiFile.Directory.FullName, midiFile.Name + ".click.wav");
            Console.WriteLine("Writing click track to '{0}'", outWaveFile);

            var format = new WaveFormatChunk();
            format.dwSamplesPerSec = (uint)samplesPerSec;
            format.wChannels = (ushort)channels;
            format.wBitsPerSample = (ushort)bitsPerSample;
            Console.WriteLine(
                "Sample rate = {0,6} Hz; Channels = {1,1}; BitsPerSample = {2,2}",
                format.dwSamplesPerSec,
                format.wChannels,
                format.wBitsPerSample
            );

            // Open the WAVE for output:
            using (var wav = File.Open(outWaveFile, FileMode.Create, FileAccess.Write, FileShare.Read))
            using (var bs = new BufferedStream(wav))
            using (var bw = new BinaryWriter(bs))
            {
                var header = new WaveHeader();

                // Write the header
                bw.Write(header.sGroupID.ToCharArray());
                bw.Write(header.dwFileLength);
                bw.Write(header.sRiffType.ToCharArray());

                // Write the format chunk
                bw.Write(format.sChunkID.ToCharArray());
                bw.Write(format.dwChunkSize);
                bw.Write(format.wFormatTag);
                bw.Write(format.wChannels);
                bw.Write(format.dwSamplesPerSec);
                bw.Write(format.dwAvgBytesPerSec);
                bw.Write(format.wBlockAlign);
                bw.Write(format.wBitsPerSample);

                var data = new WaveDataChunk();

                // Write the data chunk
                bw.Write(data.sChunkID.ToCharArray());
                bw.Write(data.dwChunkSize);

                double lastSample = sample;
                int nextBeatTick = 0;
                int note = 0;
                int tick = 0;

                using (var en = timeChanges.GetEnumerator())
                {
                    MidiEvent nextEvent;
                    bool haveKeyOrTempoChange = en.MoveNext();
                    var me = en.Current;
                    nextEvent = me.ev;

                    while (tick < lastEvent.AbsoluteTicks)
                    {
                        for (; tick < nextEvent.AbsoluteTicks; ++tick)
                        {
                            // Start a click at this tick:
                            if (tick == nextBeatTick)
                            {
                                int beat = note;
                                //Debug.WriteLine("Click at tick {0,7}, sample {1,12:#######0.00}, beat {2,2}", tick, sample, beat);

                                // Copy in a click:
                                double vol = doAttenuateBeat(beat) ? 0.3d : 1d;

                                // Silence until start of this click:
                                int x = (int)((long)sample - (long)lastSample);
                                for (; x > 0; --x)
                                {
                                    for (int j = 0; j < channels; ++j)
                                        bw.Write((short)0);
                                }

                                // Choose the click sound based on the beat:
                                short[,] click = (beat == 0) ? pinglo : pinghi;
                                int clickLength = (beat == 0) ? pingloLength : pinghiLength;

                                // Write the portion of the click if we missed the start:
                                int samplesWritten = 0;
                                long delta = x;
                                for (x = -x; x < clickLength; ++x, ++samplesWritten)
                                {
                                    int y = (int)((double)x * 48000d / (double)samplesPerSec);
                                    if (y >= clickLength) break;

                                    for (int j = 0; j < channels; ++j)
                                        bw.Write((short)(click[y, j] * vol));
                                }

                                lastSample = sample + samplesWritten + delta;

                                // Set next beat tick:
                                nextBeatTick = tick + beatTicks;
                                note = (note + 1) % getNumerator();
                            }

                            sample += samplesPerTick;
                        }

                        if (haveKeyOrTempoChange)
                        {
                            if (me.mm.MetaType == MetaType.Tempo)
                            {
                                currentTempo = new TempoMessage(me.mm);
                                calcUsecPerTick();
                                Console.WriteLine(
                                    "{0,9}: tempo {1,8:###0.000} bpm = {2,9:#,###,##0} usec/qtr",
                                    me.ev.AbsoluteTicks,
                                    500000d / currentTempo.MicrosecondsPerQuarter * 120,
                                    currentTempo.MicrosecondsPerQuarter
                                );
                            }
                            else
                            {
                                currentTimeSignature = new TimeSignatureMessage(me.mm);
                                calcBeatTicks();
            #if false
                                // NOTE: Assume key change is on a beat tick; force a reset of beats anyway.
                                //nextBeatTick = tick;
                                //note = 0;
            #endif
                                Console.WriteLine(
                                    "{0,9}: meter {1,2}/{2,-2} treating as {3,2}/{4,-2}",
                                    me.ev.AbsoluteTicks,
                                    currentTimeSignature.Numerator, currentTimeSignature.Denominator,
                                    getNumerator(), getDenominator()
                                );
                            }

                            haveKeyOrTempoChange = en.MoveNext();
                            if (haveKeyOrTempoChange)
                            {
                                me = en.Current;
                                nextEvent = me.ev;
                            }
                            else
                            {
                                me = null;
                                nextEvent = lastEvent;
                            }
                        }
                    }
                }

                // Write RIFF file size:
                bw.Seek(4, SeekOrigin.Begin);
                uint filesize = (uint)wav.Length;
                bw.Write(filesize - 8);

                // Write "data" chunk size:
                bw.Seek(0x28, SeekOrigin.Begin);
                bw.Write(filesize - 0x2C);
            }

            Console.WriteLine("Click track written to '{0}'", outWaveFile);
            Console.WriteLine(
                "Sample rate = {0,6} Hz; Channels = {1,1}; BitsPerSample = {2,2}",
                format.dwSamplesPerSec,
                format.wChannels,
                format.wBitsPerSample
            );
        }
Пример #31
0
 public static extern int waveOutWrite(IntPtr hwo, ref WaveHeader pwh, int cbwh);
Пример #32
0
        // made non-static so that playing can be stopped here
        private void Callback(IntPtr hWaveOut, WaveInterop.WaveMessage uMsg, IntPtr dwUser, WaveHeader wavhdr,
                              IntPtr dwReserved)
        {
            if (uMsg == WaveInterop.WaveMessage.WaveOutDone)
            {
                // check that we're not here through pressing stop
                var hBuffer = (GCHandle)wavhdr.userData;
                var buffer  = (WaveOutBuffer)hBuffer.Target;

                lock (actionQueue)
                {
                    actionQueue.Enqueue(new WaveOutAction(WaveOutFunction.BufferDone, buffer));
                    workAvailable.Set();
                }

                // n.b. this was wrapped in an exception handler, but bug should be fixed now
            }
        }
Пример #33
0
        /// <summary>
        /// 文本合成
        /// </summary>
        /// <param name="text"></param>
        /// <param name="param"></param>
        /// <param name="waveFile"></param>
        public void TextToSpeech(string text,string param,string waveFile)
        {
            byte[] bytes = null;
            int ret = 0;
            try
            {
                sessionID=Marshal.PtrToStringAuto(MSCDLL.QTTSSessionBegin(param,ref ret));
                //UnityEngine.Debug.Log(sessionID);
                if (ret!=(int)ErrorCode.MSP_SUCCESS)
                {
                    if (onErrorEvent!=null)
                        onErrorEvent.Invoke("初始化出错."+ret);
                    return;
                }
                //  UnityEngine.Debug.Log("初始化成功");
                ret=MSCDLL.QTTSTextPut(sessionID,text,(uint)Encoding.Unicode.GetByteCount(text),string.Empty);
                if (ret!=(int)ErrorCode.MSP_SUCCESS)
                {
                    if (onErrorEvent!=null)
                        onErrorEvent.Invoke("发生数据出错."+ret);
                    return;
                }
                //  UnityEngine.Debug.Log("发生数据成功");
                IntPtr audioData;
                uint audioLen = 0;
                SynthStatus synthStatus = SynthStatus.MSP_TTS_FLAG_STILL_HAVE_DATA;
                using (MemoryStream ms = new MemoryStream())
                {
                    ms.Write(new byte[44],0,44);
                    while (synthStatus==SynthStatus.MSP_TTS_FLAG_STILL_HAVE_DATA)
                    {
                        audioData = MSCDLL.QTTSAudioGet(sessionID,ref audioLen,ref synthStatus,ref ret);
                        if (audioData!=IntPtr.Zero)
                        {
                            byte[] data = new byte[audioLen];
                            Marshal.Copy(audioData,data,0,data.Length);
                            ms.Write(data,0,data.Length);
                            if (synthStatus==SynthStatus.MSP_TTS_FLAG_DATA_END||ret!=(int)ErrorCode.MSP_SUCCESS)
                            {
                                if (ret!=(int)ErrorCode.MSP_SUCCESS)
                                {
                                    if (onErrorEvent!=null)
                                        onErrorEvent.Invoke("下载文件错误."+ret);
                                    return;
                                }
                                break;
                            }
                        }
                        Thread.Sleep(150);
                    }
                    //UnityEngine.Debug.Log("wav header");
                    WaveHeader header = GetWaveHeader((int)ms.Length-44);
                    byte[] headerByte = StructToBytes(header);
                    ms.Position=0;
                    ms.Write(headerByte,0,headerByte.Length);
                    bytes=ms.ToArray();
                    ms.Close();
                }
                if (waveFile!=null)
                {
                    if (File.Exists(waveFile))
                    {
                        File.Delete(waveFile);
                    }
                    File.WriteAllBytes(waveFile,bytes);
                }

            }
            catch (Exception ex)
            {
                if (onErrorEvent!=null) onErrorEvent.Invoke("Error:"+ex.Message);
                return;
            }
            finally
            {
                ret =MSCDLL.QTTSSessionEnd(sessionID,"");
                if (ret !=(int)ErrorCode.MSP_SUCCESS)
                {
                    if (onErrorEvent!=null)
                        onErrorEvent.Invoke("结束时出错."+ret);
                }
                else
                {
                    if (onFinishEvent!=null)
                        onFinishEvent.Invoke(text,bytes);
                }
            }
        }
Пример #34
0
		/**
		 * Saves selected frame span to a new file.
		 *
		 * @param filename where to save frames
		 * @param begin number of the first frame
		 * @param end number of the last frame
		 * @throw FormatException not allowed to save 8b-mono files
		 */
		public void SaveFrames(string filename, int begin, int end)
		{
			if (1 == hdr.Channels && 8 == hdr.BitsPerSamp)
			{
				throw new FormatException("Save error: 8-bit mono files are not supported yet!");
			}
			int samples = GetSamplesPerFrame();
			
			// calculate the boundaries of a fragment of the source channel
			// which correspond to given frame numbers
			int startPos = (int)(begin * samples * (1 - overlap));
			int endPos = (int)((end + 1) * samples * (1 - overlap) + samples * overlap);
			if (endPos > LChTab.Count)
				endPos = LChTab.Count;
			
			// number of data bytes in the resulting wave file
			UInt32 waveSize = (UInt32) (endPos - startPos) * hdr.BytesPerSamp;
			
			// prepare a new header and write it to file stream
			WaveHeader newHdr = new WaveHeader();
			//std.strncpy(newHdr.RIFF, hdr.RIFF, 4);
			newHdr.DataLength = (UInt32) (waveSize + newHdr.WaveHeaderSize);
			//std.strncpy(newHdr.WAVE, hdr.WAVE, 4);
			//std.strncpy(newHdr.fmt_, hdr.fmt_, 4);
			newHdr.SubBlockLength = hdr.SubBlockLength;
			newHdr.formatTag = hdr.formatTag;
			newHdr.Channels = hdr.Channels;
			newHdr.SampFreq = hdr.SampFreq;
			newHdr.BytesPerSec = hdr.BytesPerSec;
			newHdr.BytesPerSamp = hdr.BytesPerSamp;
			newHdr.BitsPerSamp = hdr.BitsPerSamp;
			//std.strncpy(newHdr.data, hdr.data, 4);
			newHdr.WaveSize = waveSize;
			
			BinaryFile fs = new BinaryFile(filename);
			//fs.write((string) newHdr, sizeof(WaveHeader));
			fs.Write(newHdr.RIFF);
			fs.Write(newHdr.DataLength);
			fs.Write(newHdr.WAVE);
			fs.Write(newHdr.fmt_);
			fs.Write(newHdr.SubBlockLength);
			fs.Write(newHdr.formatTag);
			fs.Write(newHdr.Channels);
			fs.Write(newHdr.SampFreq);
			fs.Write(newHdr.BytesPerSec);
			fs.Write(newHdr.BytesPerSamp);
			fs.Write(newHdr.BitsPerSamp);
			fs.Write(newHdr.data);
			fs.Write(newHdr.WaveSize);
			
			// convert our data from source channels to a temporary buffer
			short[] data = new short[waveSize/2];
			for (int i = startPos, di = 0; i < endPos; ++i, ++di)
			{
				if (16 == hdr.BitsPerSamp)
				{
					if (2 == hdr.Channels)
					{
						data[2 *di] = LChTab[i];
						data[2 *di+1] = RChTab[i];
					}
					else
					{
						data[di] = LChTab[i];
					}
				}
				else
				{
					if (2 == hdr.Channels)
					{
						//data[di/2] = ((RChTab[i] + 128) << 8) | (LChTab[i] + 128);
					}
				}
			}
			
			// write the raw data to file and clean the buffer
			for (int i = 0; i < data.Length; i++) {
				fs.Write(data[i]);
			}
			fs.Close();
			data = null;
		}
Пример #35
0
        public unsafe static void Save(Song song, string filename, int sampleRate)
        {
            var advance      = true;
            var tempoCounter = 0;
            var playPattern  = 0;
            var playNote     = 0;
            var speed        = song.Speed;
            var wavBytes     = new List <byte>();
            var apuIndex     = NesApu.APU_WAV_EXPORT;
            var dmcCallback  = new NesApu.DmcReadDelegate(NesApu.DmcReadCallback);

            NesApu.NesApuInit(apuIndex, sampleRate, dmcCallback);
            NesApu.Reset(apuIndex);

            var channels = new ChannelState[5]
            {
                new SquareChannelState(apuIndex, 0),
                new SquareChannelState(apuIndex, 1),
                new TriangleChannelState(apuIndex, 2),
                new NoiseChannelState(apuIndex, 3),
                new DPCMChannelState(apuIndex, 4)
            };

            for (int i = 0; i < 5; i++)
            {
                NesApu.NesApuEnableChannel(apuIndex, i, 1);
            }

            while (true)
            {
                // Advance to next note.
                if (advance)
                {
                    foreach (var channel in channels)
                    {
                        channel.ProcessEffects(song, ref playPattern, ref playNote, ref speed, false);
                    }

                    foreach (var channel in channels)
                    {
                        channel.Advance(song, playPattern, playNote);
                    }

                    advance = false;
                }

                // Update envelopes + APU registers.
                foreach (var channel in channels)
                {
                    channel.UpdateEnvelopes();
                    channel.UpdateAPU();
                }

                NesApu.NesApuEndFrame(apuIndex);

                int    numTotalSamples = NesApu.NesApuSamplesAvailable(apuIndex);
                byte[] samples         = new byte[numTotalSamples * 2];

                fixed(byte *ptr = &samples[0])
                {
                    NesApu.NesApuReadSamples(apuIndex, new IntPtr(ptr), numTotalSamples);
                }

                wavBytes.AddRange(samples);

                int dummy1 = 0;
                if (!PlayerBase.AdvanceTempo(song, speed, LoopMode.None, ref tempoCounter, ref playPattern, ref playNote, ref dummy1, ref advance))
                {
                    break;
                }
            }

            using (var file = new FileStream(filename, FileMode.Create))
            {
                var header = new WaveHeader();

                // RIFF WAVE Header
                header.chunkId[0] = (byte)'R';
                header.chunkId[1] = (byte)'I';
                header.chunkId[2] = (byte)'F';
                header.chunkId[3] = (byte)'F';
                header.format[0]  = (byte)'W';
                header.format[1]  = (byte)'A';
                header.format[2]  = (byte)'V';
                header.format[3]  = (byte)'E';

                // Format subchunk
                header.subChunk1Id[0] = (byte)'f';
                header.subChunk1Id[1] = (byte)'m';
                header.subChunk1Id[2] = (byte)'t';
                header.subChunk1Id[3] = (byte)' ';
                header.audioFormat    = 1;          // FOR PCM
                header.numChannels    = 1;          // 1 for MONO, 2 for stereo
                header.sampleRate     = sampleRate; // ie 44100 hertz, cd quality audio
                header.bitsPerSample  = 16;         //
                header.byteRate       = header.sampleRate * header.numChannels * header.bitsPerSample / 8;
                header.blockAlign     = (short)(header.numChannels * header.bitsPerSample / 8);

                // Data subchunk
                header.subChunk2Id[0] = (byte)'d';
                header.subChunk2Id[1] = (byte)'a';
                header.subChunk2Id[2] = (byte)'t';
                header.subChunk2Id[3] = (byte)'a';

                // All sizes for later:
                // chuckSize = 4 + (8 + subChunk1Size) + (8 + subChubk2Size)
                // subChunk1Size is constanst, i'm using 16 and staying with PCM
                // subChunk2Size = nSamples * nChannels * bitsPerSample/8
                // Whenever a sample is added:
                //    chunkSize += (nChannels * bitsPerSample/8)
                //    subChunk2Size += (nChannels * bitsPerSample/8)
                header.subChunk1Size = 16;
                header.subChunk2Size = wavBytes.Count;
                header.chunkSize     = 4 + (8 + header.subChunk1Size) + (8 + header.subChunk2Size);

                var headerBytes = new byte[sizeof(WaveHeader)];
                Marshal.Copy(new IntPtr(&header), headerBytes, 0, headerBytes.Length);
                file.Write(headerBytes, 0, headerBytes.Length);
                file.Write(wavBytes.ToArray(), 0, wavBytes.Count);
            }
        }
Пример #36
0
 public static extern int waveOutPrepareHeader(IntPtr hwo, ref WaveHeader pwh, int cbwh);
Пример #37
0
 public static extern int waveInAddBuffer(IntPtr hwi, ref WaveHeader pwh, int cbwh);
Пример #38
0
 public static extern int waveInUnprepareHeader(IntPtr hwi, ref WaveHeader pwh, int cbwh);