public void PlayStreaming(Stream stream) { VorbisCodec codec = new VorbisCodec(); AudioFormat fmt = codec.ReadHeader(stream); SetFormat(fmt); IEnumerator <AudioChunk> chunks = codec.StreamData(stream).GetEnumerator(); AudioChunk tmp = new AudioChunk(); // largest possible vorbis frame decodes to blocksize1 samples // so we may end up decoding slightly over a second of audio int chunkSize = (fmt.SampleRate + 8192) * fmt.Channels * sizeof(short); byte[][] data = new byte[NumBuffers][]; for (int i = 0; i < NumBuffers; i++) { data[i] = new byte[chunkSize]; } bool reachedEnd = false; for (int i = 0; i < NumBuffers && !reachedEnd; i++) { tmp.Data = data[i]; reachedEnd = BufferBlock(tmp, fmt, chunks); BufferData(i, tmp); } Play(); for (; !reachedEnd;) { int next = -1; for (int i = 0; i < NumBuffers; i++) { if (IsCompleted(i)) { next = i; break; } } if (next == -1) { Thread.Sleep(10); continue; } if (pendingStop) { break; } tmp.Data = data[next]; reachedEnd = BufferBlock(tmp, fmt, chunks); BufferData(next, tmp); } while (!IsFinished()) { Thread.Sleep(10); } }
public override void BufferData(int index, AudioChunk chunk) { fixed(byte *data = chunk.Data) { uint buffer = bufferIDs[index]; completed[index] = false; AL.alBufferData(buffer, dataFormat, (IntPtr)data, chunk.Length, Format.SampleRate); CheckError("BufferData"); AL.alSourceQueueBuffers(source, 1, &buffer); CheckError("QueueBuffers"); } }
void ApplyVolume(IntPtr handle, AudioChunk chunk) { if (volumePercent == 100) { return; } if (Format.BitsPerSample == 16) { VolumeMixer.Mix16((short *)handle, chunk.Length / sizeof(short), volumePercent); } else if (Format.BitsPerSample == 8) { VolumeMixer.Mix8((byte *)handle, chunk.Length, volumePercent); } }
bool BufferBlock(AudioChunk tmp, AudioFormat fmt, IEnumerator <AudioChunk> chunks) { // decode up to around a second int secondSize = fmt.SampleRate * fmt.Channels * sizeof(short); tmp.Length = 0; while (tmp.Length < secondSize) { if (!chunks.MoveNext()) { return(true); } AudioChunk src = chunks.Current; Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length); tmp.Length += src.Length; } return(false); }
bool BufferBlock(int i, AudioChunk tmp, int size, IEnumerator <AudioChunk> chunks) { tmp.Length = 0; bool end = false; while (tmp.Length < size) { if (!chunks.MoveNext()) { end = true; break; } AudioChunk src = chunks.Current; Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length); tmp.Length += src.Length; } BufferData(i, tmp); return(end); }
public override void BufferData(int index, AudioChunk chunk) { if (chunk.Length > dataSizes[index]) { IntPtr ptr = dataHandles[index]; if (ptr != IntPtr.Zero) { Marshal.FreeHGlobal(ptr); } dataHandles[index] = Marshal.AllocHGlobal(chunk.Length); } IntPtr handle = dataHandles[index]; fixed(byte *data = chunk.Data) { MemUtils.memcpy((IntPtr)data, handle, chunk.Length); ApplyVolume(handle, chunk); } WaveHeader header = default(WaveHeader); header.DataBuffer = handle; header.BufferLength = chunk.Length; header.Loops = 1; WaveHeader *hdr = (WaveHeader *)headers + index; *hdr = header; uint result = WinMM.waveOutPrepareHeader(devHandle, (IntPtr)hdr, waveHeaderSize); CheckError(result, "PrepareHeader"); result = WinMM.waveOutWrite(devHandle, (IntPtr)hdr, waveHeaderSize); CheckError(result, "Write"); }
public void PlayData(int index, AudioChunk chunk) { BufferData(index, chunk); Play(); }
public abstract void BufferData(int index, AudioChunk chunk);
public VorbisCodec() { chunk = new AudioChunk(); }