mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 18:15:28 -04:00
Simplify SharpWave even more. (and fix a memory leak in C client)
This commit is contained in:
parent
c731192f1c
commit
e5b43b263c
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
# Visual Studio 2010
|
# Visual Studio 2008
|
||||||
# SharpDevelop 4.4
|
# SharpDevelop 4.4
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassicalSharp", "ClassicalSharp\ClassicalSharp.csproj", "{BEB1C785-5CAD-48FF-A886-876BF0A318D4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassicalSharp", "ClassicalSharp\ClassicalSharp.csproj", "{BEB1C785-5CAD-48FF-A886-876BF0A318D4}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -3,7 +3,6 @@ using System;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using ClassicalSharp.Events;
|
using ClassicalSharp.Events;
|
||||||
using SharpWave;
|
using SharpWave;
|
||||||
using SharpWave.Codecs;
|
|
||||||
|
|
||||||
namespace ClassicalSharp.Audio {
|
namespace ClassicalSharp.Audio {
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using SharpWave;
|
using SharpWave;
|
||||||
using SharpWave.Codecs.Vorbis;
|
|
||||||
|
|
||||||
namespace ClassicalSharp.Audio {
|
namespace ClassicalSharp.Audio {
|
||||||
|
|
||||||
@ -79,10 +78,9 @@ namespace ClassicalSharp.Audio {
|
|||||||
|
|
||||||
string path = Path.Combine("audio", file);
|
string path = Path.Combine("audio", file);
|
||||||
using (Stream fs = Platform.FileOpen(path)) {
|
using (Stream fs = Platform.FileOpen(path)) {
|
||||||
OggContainer container = new OggContainer(fs);
|
|
||||||
try {
|
try {
|
||||||
musicOut.SetVolume(game.MusicVolume / 100.0f);
|
musicOut.SetVolume(game.MusicVolume / 100.0f);
|
||||||
musicOut.PlayStreaming(container);
|
musicOut.PlayStreaming(fs);
|
||||||
} catch (InvalidOperationException ex) {
|
} catch (InvalidOperationException ex) {
|
||||||
HandleMusicError(ex);
|
HandleMusicError(ex);
|
||||||
try { musicOut.Dispose(); } catch { }
|
try { musicOut.Dispose(); } catch { }
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using ClassicalSharp;
|
using ClassicalSharp;
|
||||||
using ClassicalSharp.Network;
|
using ClassicalSharp.Network;
|
||||||
using SharpWave;
|
using SharpWave;
|
||||||
using SharpWave.Codecs.Vorbis;
|
|
||||||
|
|
||||||
namespace Launcher.Patcher {
|
namespace Launcher.Patcher {
|
||||||
|
|
||||||
@ -60,25 +59,26 @@ namespace Launcher.Patcher {
|
|||||||
string path = Path.Combine("audio", prefix + name + ".wav");
|
string path = Path.Combine("audio", prefix + name + ".wav");
|
||||||
|
|
||||||
using (Stream dst = Platform.FileCreate(path))
|
using (Stream dst = Platform.FileCreate(path))
|
||||||
using (MemoryStream src = new MemoryStream(rawData))
|
using (MemoryStream src = new MemoryStream(rawData))
|
||||||
{
|
{
|
||||||
dst.SetLength(44);
|
dst.SetLength(44);
|
||||||
RawOut output = new RawOut((FileStream)dst, true);
|
VorbisCodec codec = new VorbisCodec();
|
||||||
output.Create(1);
|
AudioFormat format = codec.ReadHeader(src);
|
||||||
OggContainer container = new OggContainer(src);
|
|
||||||
output.PlayStreaming(container);
|
foreach (AudioChunk chunk in codec.StreamData(src)) {
|
||||||
|
dst.Write(chunk.Data, 0, chunk.Length);
|
||||||
|
}
|
||||||
|
|
||||||
dst.Position = 0;
|
dst.Position = 0;
|
||||||
BinaryWriter w = new BinaryWriter(dst);
|
BinaryWriter w = new BinaryWriter(dst);
|
||||||
WriteWaveHeader(w, dst, output);
|
WriteWaveHeader(w, dst, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteWaveHeader(BinaryWriter w, Stream stream, RawOut data) {
|
void WriteWaveHeader(BinaryWriter w, Stream stream, AudioFormat format) {
|
||||||
WriteFourCC(w, "RIFF");
|
WriteFourCC(w, "RIFF");
|
||||||
w.Write((int)(stream.Length - 8));
|
w.Write((int)(stream.Length - 8));
|
||||||
WriteFourCC(w, "WAVE");
|
WriteFourCC(w, "WAVE");
|
||||||
AudioFormat format = data.Format;
|
|
||||||
|
|
||||||
WriteFourCC(w, "fmt ");
|
WriteFourCC(w, "fmt ");
|
||||||
w.Write(16);
|
w.Write(16);
|
||||||
|
@ -44,9 +44,9 @@ namespace OpenTK.Audio.OpenAL {
|
|||||||
public static extern void alGenBuffers(int n, uint* bids);
|
public static extern void alGenBuffers(int n, uint* bids);
|
||||||
[DllImport(lib, CallingConvention = style)]
|
[DllImport(lib, CallingConvention = style)]
|
||||||
public static extern void alDeleteBuffers(int n, uint* bids);
|
public static extern void alDeleteBuffers(int n, uint* bids);
|
||||||
|
|
||||||
[DllImport(lib, CallingConvention = style)]
|
[DllImport(lib, CallingConvention = style)]
|
||||||
public static extern void alBufferData(uint bid, ALFormat format, IntPtr buffer, int size, int freq);
|
public static extern void alBufferData(uint bid, ALFormat format, IntPtr buffer, int size, int freq);
|
||||||
|
|
||||||
[DllImport(lib, CallingConvention = style)]
|
[DllImport(lib, CallingConvention = style)]
|
||||||
public static extern IntPtr alcCreateContext(IntPtr device, int* attrlist);
|
public static extern IntPtr alcCreateContext(IntPtr device, int* attrlist);
|
||||||
[DllImport(lib, CallingConvention = style)]
|
[DllImport(lib, CallingConvention = style)]
|
||||||
@ -79,7 +79,6 @@ namespace OpenTK.Audio.OpenAL {
|
|||||||
public enum ALError {
|
public enum ALError {
|
||||||
NoError = 0,
|
NoError = 0,
|
||||||
InvalidName = 0xA001,
|
InvalidName = 0xA001,
|
||||||
IllegalEnum = 0xA002,
|
|
||||||
InvalidEnum = 0xA002,
|
InvalidEnum = 0xA002,
|
||||||
InvalidValue = 0xA003,
|
InvalidValue = 0xA003,
|
||||||
InvalidOperation = 0xA004,
|
InvalidOperation = 0xA004,
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using SharpWave.Codecs;
|
|
||||||
using SharpWave.Containers;
|
|
||||||
|
|
||||||
namespace SharpWave {
|
namespace SharpWave {
|
||||||
|
|
||||||
@ -15,6 +13,11 @@ namespace SharpWave {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class AudioChunk {
|
||||||
|
public byte[] Data;
|
||||||
|
public int Length;
|
||||||
|
}
|
||||||
|
|
||||||
public delegate void Action();
|
public delegate void Action();
|
||||||
|
|
||||||
public abstract class IAudioOutput : IDisposable {
|
public abstract class IAudioOutput : IDisposable {
|
||||||
@ -30,14 +33,12 @@ namespace SharpWave {
|
|||||||
|
|
||||||
public int NumBuffers;
|
public int NumBuffers;
|
||||||
public bool pendingStop;
|
public bool pendingStop;
|
||||||
public void PlayStreaming(IMediaContainer container) {
|
public void PlayStreaming(Stream src) {
|
||||||
container.ReadMetadata();
|
VorbisCodec codec = new VorbisCodec();
|
||||||
ICodec codec = container.GetAudioCodec();
|
AudioFormat format = codec.ReadHeader(src);
|
||||||
AudioFormat format = codec.ReadHeader(container);
|
|
||||||
|
|
||||||
SetFormat(format);
|
SetFormat(format);
|
||||||
IEnumerator<AudioChunk> chunks =
|
IEnumerator<AudioChunk> chunks = codec.StreamData(src).GetEnumerator();
|
||||||
codec.StreamData(container).GetEnumerator();
|
|
||||||
|
|
||||||
bool reachedEnd = false;
|
bool reachedEnd = false;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -59,36 +60,4 @@ namespace SharpWave {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Outputs raw audio to the given stream in the constructor. </summary>
|
|
||||||
public unsafe sealed partial class RawOut : IAudioOutput {
|
|
||||||
public readonly Stream OutStream;
|
|
||||||
public readonly bool LeaveOpen;
|
|
||||||
public Action OnGotMetadata;
|
|
||||||
|
|
||||||
public RawOut(FileStream outStream, bool leaveOpen) {
|
|
||||||
OutStream = outStream;
|
|
||||||
LeaveOpen = leaveOpen;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Create(int numBuffers) { NumBuffers = numBuffers; }
|
|
||||||
public override void SetVolume(float volume) { }
|
|
||||||
|
|
||||||
public override void SetFormat(AudioFormat format) {
|
|
||||||
Format = format;
|
|
||||||
if (OnGotMetadata != null) OnGotMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void PlayData(int index, AudioChunk chunk) {
|
|
||||||
OutStream.Write(chunk.Data, 0, chunk.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose() {
|
|
||||||
if (LeaveOpen) return;
|
|
||||||
OutStream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsCompleted(int index) { return true; }
|
|
||||||
public override bool IsFinished() { return true; }
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using OpenTK.Audio;
|
using OpenTK.Audio;
|
||||||
using OpenTK.Audio.OpenAL;
|
using OpenTK.Audio.OpenAL;
|
||||||
using SharpWave.Codecs;
|
|
||||||
|
|
||||||
namespace SharpWave {
|
namespace SharpWave {
|
||||||
|
|
||||||
|
@ -28,8 +28,7 @@ namespace SharpWave {
|
|||||||
internal static string GetErrorDescription(uint error) {
|
internal static string GetErrorDescription(uint error) {
|
||||||
StringBuilder message = new StringBuilder(1024);
|
StringBuilder message = new StringBuilder(1024);
|
||||||
uint result = waveOutGetErrorText(error, message, message.Capacity);
|
uint result = waveOutGetErrorText(error, message, message.Capacity);
|
||||||
if(result == 0)
|
if (result == 0) return message.ToString();
|
||||||
return message.ToString();
|
|
||||||
return "waveOutGetErrorText failed.";
|
return "waveOutGetErrorText failed.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,8 +60,5 @@ namespace SharpWave {
|
|||||||
public enum WaveHeaderFlags : uint {
|
public enum WaveHeaderFlags : uint {
|
||||||
Done = 0x01,
|
Done = 0x01,
|
||||||
Prepared = 0x02,
|
Prepared = 0x02,
|
||||||
BeginLoop = 0x04,
|
|
||||||
EndLoop = 0x08,
|
|
||||||
InQueue = 0x10,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using SharpWave.Codecs;
|
|
||||||
|
|
||||||
namespace SharpWave {
|
namespace SharpWave {
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace SharpWave.Codecs {
|
|
||||||
|
|
||||||
public interface ICodec {
|
|
||||||
AudioFormat ReadHeader(Stream source);
|
|
||||||
IEnumerable<AudioChunk> StreamData(Stream source);
|
|
||||||
string Name { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class AudioChunk {
|
|
||||||
public byte[] Data;
|
|
||||||
public int Length;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using SharpWave.Codecs;
|
|
||||||
|
|
||||||
namespace SharpWave.Containers {
|
|
||||||
|
|
||||||
public abstract class IMediaContainer : Stream {
|
|
||||||
protected Stream stream;
|
|
||||||
public IMediaContainer(Stream source) { stream = source; }
|
|
||||||
|
|
||||||
public abstract void ReadMetadata();
|
|
||||||
|
|
||||||
public abstract ICodec GetAudioCodec();
|
|
||||||
|
|
||||||
#region Stream implementation
|
|
||||||
|
|
||||||
public override bool CanRead { get { return true; } }
|
|
||||||
public override bool CanSeek { get { return false; } }
|
|
||||||
public override bool CanWrite { get { return false; } }
|
|
||||||
public override void Flush() { stream.Flush(); }
|
|
||||||
public override long Length { get { return stream.Length; } }
|
|
||||||
|
|
||||||
public override long Position {
|
|
||||||
get { return stream.Position; }
|
|
||||||
set { stream.Position = value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek( long offset, SeekOrigin origin ) {
|
|
||||||
return stream.Seek( offset, origin );
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetLength( long value ) {
|
|
||||||
throw new NotImplementedException( "SharpWave is only a decoder" );
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count) {
|
|
||||||
return stream.Read(buffer, offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int ReadByte() { return stream.ReadByte(); }
|
|
||||||
|
|
||||||
public override void Write( byte[] buffer, int offset, int count ) {
|
|
||||||
throw new NotImplementedException( "SharpWave is only a decoder" );
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
@ -61,21 +61,17 @@
|
|||||||
<Compile Include="csvorbis\Ogg\SyncState.cs" />
|
<Compile Include="csvorbis\Ogg\SyncState.cs" />
|
||||||
<Compile Include="csvorbis\StaticCodeBook.cs" />
|
<Compile Include="csvorbis\StaticCodeBook.cs" />
|
||||||
<Compile Include="csvorbis\VUtils.cs" />
|
<Compile Include="csvorbis\VUtils.cs" />
|
||||||
<Compile Include="ICodec.cs" />
|
|
||||||
<Compile Include="IMediaContainer.cs" />
|
|
||||||
<Compile Include="Backends\AL.cs" />
|
<Compile Include="Backends\AL.cs" />
|
||||||
<Compile Include="Backends\WinMM.cs" />
|
<Compile Include="Backends\WinMM.cs" />
|
||||||
<Compile Include="Backends\OpenALOut.cs" />
|
<Compile Include="Backends\OpenALOut.cs" />
|
||||||
<Compile Include="Backends\WinMmOut.cs" />
|
<Compile Include="Backends\WinMmOut.cs" />
|
||||||
|
<Compile Include="Utils.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Utils\MemUtils.cs" />
|
|
||||||
<Compile Include="Backends\IAudioOutput.cs" />
|
<Compile Include="Backends\IAudioOutput.cs" />
|
||||||
<Compile Include="VolumeMixer.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="csvorbis\Ogg" />
|
<Folder Include="csvorbis\Ogg" />
|
||||||
<Folder Include="csvorbis" />
|
<Folder Include="csvorbis" />
|
||||||
<Folder Include="Utils" />
|
|
||||||
<Folder Include="Backends" />
|
<Folder Include="Backends" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,6 +2,37 @@
|
|||||||
|
|
||||||
namespace SharpWave {
|
namespace SharpWave {
|
||||||
|
|
||||||
|
public static class MemUtils {
|
||||||
|
|
||||||
|
static MemUtils() {
|
||||||
|
use64Bit = IntPtr.Size == 8;
|
||||||
|
}
|
||||||
|
static bool use64Bit;
|
||||||
|
|
||||||
|
public static unsafe void memcpy( IntPtr srcPtr, IntPtr dstPtr, int bytes ) {
|
||||||
|
byte* srcByte, dstByte;
|
||||||
|
if( use64Bit ) {
|
||||||
|
ulong* srcLong = (ulong*)srcPtr, dstLong = (ulong*)dstPtr;
|
||||||
|
while( bytes >= 8 ) {
|
||||||
|
*dstLong++ = *srcLong++;
|
||||||
|
bytes -= 8;
|
||||||
|
}
|
||||||
|
srcByte = (byte*)srcLong; dstByte = (byte*)dstLong;
|
||||||
|
} else {
|
||||||
|
uint* srcInt = (uint*)srcPtr, dstInt = (uint*)dstPtr;
|
||||||
|
while( bytes >= 4 ) {
|
||||||
|
*dstInt++ = *srcInt++;
|
||||||
|
bytes -= 4;
|
||||||
|
}
|
||||||
|
srcByte = (byte*)srcInt; dstByte = (byte*)dstInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = 0; i < bytes; i++ ) {
|
||||||
|
*dstByte++ = *srcByte++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe static class VolumeMixer {
|
public unsafe static class VolumeMixer {
|
||||||
|
|
||||||
public static void Mix16( short* samples, int numSamples, int volumePercent ) {
|
public static void Mix16( short* samples, int numSamples, int volumePercent ) {
|
||||||
@ -36,4 +67,4 @@ namespace SharpWave {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,35 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace SharpWave {
|
|
||||||
|
|
||||||
public static class MemUtils {
|
|
||||||
|
|
||||||
static MemUtils() {
|
|
||||||
use64Bit = IntPtr.Size == 8;
|
|
||||||
}
|
|
||||||
static bool use64Bit;
|
|
||||||
|
|
||||||
public static unsafe void memcpy( IntPtr srcPtr, IntPtr dstPtr, int bytes ) {
|
|
||||||
byte* srcByte, dstByte;
|
|
||||||
if( use64Bit ) {
|
|
||||||
ulong* srcLong = (ulong*)srcPtr, dstLong = (ulong*)dstPtr;
|
|
||||||
while( bytes >= 8 ) {
|
|
||||||
*dstLong++ = *srcLong++;
|
|
||||||
bytes -= 8;
|
|
||||||
}
|
|
||||||
srcByte = (byte*)srcLong; dstByte = (byte*)dstLong;
|
|
||||||
} else {
|
|
||||||
uint* srcInt = (uint*)srcPtr, dstInt = (uint*)dstPtr;
|
|
||||||
while( bytes >= 4 ) {
|
|
||||||
*dstInt++ = *srcInt++;
|
|
||||||
bytes -= 4;
|
|
||||||
}
|
|
||||||
srcByte = (byte*)srcInt; dstByte = (byte*)dstInt;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( int i = 0; i < bytes; i++ ) {
|
|
||||||
*dstByte++ = *srcByte++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,27 +3,10 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using csogg;
|
using csogg;
|
||||||
using csvorbis;
|
using csvorbis;
|
||||||
using SharpWave.Containers;
|
|
||||||
|
|
||||||
namespace SharpWave.Codecs.Vorbis {
|
namespace SharpWave {
|
||||||
|
|
||||||
public sealed class OggContainer : IMediaContainer {
|
public sealed class VorbisCodec {
|
||||||
|
|
||||||
public OggContainer( Stream source ) : base( source ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void ReadMetadata() {
|
|
||||||
// this would be a good place to read vorbis headers
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ICodec GetAudioCodec() {
|
|
||||||
return new VorbisCodec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class VorbisCodec : ICodec {
|
|
||||||
public string Name { get { return "Xiph.org Vorbis"; } }
|
|
||||||
|
|
||||||
public VorbisCodec() {
|
public VorbisCodec() {
|
||||||
chunk = new AudioChunk();
|
chunk = new AudioChunk();
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,13 @@ struct Codebook {
|
|||||||
UInt16* Multiplicands;
|
UInt16* Multiplicands;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void Codebook_Free(struct Codebook* c) {
|
||||||
|
Mem_Free(&c->Codewords);
|
||||||
|
Mem_Free(&c->CodewordLens);
|
||||||
|
Mem_Free(&c->Values);
|
||||||
|
Mem_Free(&c->Multiplicands);
|
||||||
|
}
|
||||||
|
|
||||||
static UInt32 Codebook_Pow(UInt32 base, UInt32 exp) {
|
static UInt32 Codebook_Pow(UInt32 base, UInt32 exp) {
|
||||||
UInt32 result = 1; /* exponentiation by squaring */
|
UInt32 result = 1; /* exponentiation by squaring */
|
||||||
while (exp) {
|
while (exp) {
|
||||||
@ -267,6 +274,7 @@ static ReturnCode Codebook_DecodeSetup(struct VorbisState* ctx, struct Codebook*
|
|||||||
Mem_Free(&codewordLens);
|
Mem_Free(&codewordLens);
|
||||||
|
|
||||||
c->LookupType = Vorbis_ReadBits(ctx, 4);
|
c->LookupType = Vorbis_ReadBits(ctx, 4);
|
||||||
|
c->Multiplicands = NULL;
|
||||||
if (c->LookupType == 0) return 0;
|
if (c->LookupType == 0) return 0;
|
||||||
if (c->LookupType > 2) return VORBIS_ERR_CODEBOOK_LOOKUP;
|
if (c->LookupType > 2) return VORBIS_ERR_CODEBOOK_LOOKUP;
|
||||||
|
|
||||||
@ -704,7 +712,7 @@ static void Residue_DecodeFrame(struct VorbisState* ctx, struct Residue* r, Int3
|
|||||||
bool decodeAny = false;
|
bool decodeAny = false;
|
||||||
Int32 i, j;
|
Int32 i, j;
|
||||||
|
|
||||||
/* type 2 decodes all channel vectors 2, if at least 1 channel to decode */
|
/* type 2 decodes all channel vectors, if at least 1 channel to decode */
|
||||||
for (i = 0; i < ch; i++) {
|
for (i = 0; i < ch; i++) {
|
||||||
if (!doNotDecode[i]) decodeAny = true;
|
if (!doNotDecode[i]) decodeAny = true;
|
||||||
}
|
}
|
||||||
@ -976,17 +984,25 @@ static void Vorbis_CalcWindow(struct VorbisState* ctx, UInt32* offset, bool long
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Vorbis_Free(struct VorbisState* ctx) {
|
void Vorbis_Free(struct VorbisState* ctx) {
|
||||||
|
Int32 i;
|
||||||
|
for (i = 0; i < ctx->NumCodebooks; i++) {
|
||||||
|
Codebook_Free(&ctx->Codebooks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
Mem_Free(&ctx->Codebooks);
|
Mem_Free(&ctx->Codebooks);
|
||||||
Mem_Free(&ctx->Floors);
|
Mem_Free(&ctx->Floors);
|
||||||
Mem_Free(&ctx->Residues);
|
Mem_Free(&ctx->Residues);
|
||||||
Mem_Free(&ctx->Mappings);
|
Mem_Free(&ctx->Mappings);
|
||||||
Mem_Free(&ctx->Modes);
|
Mem_Free(&ctx->Modes);
|
||||||
Mem_Free(&ctx->WindowShort);
|
Mem_Free(&ctx->WindowShort);
|
||||||
/* TODO: free memory in codebooks, other bits, etc*/
|
|
||||||
|
Mem_Free(&ctx->Values[0]);
|
||||||
|
Mem_Free(&ctx->Values[1]);
|
||||||
|
/* TODO: free other temp memory, etc*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Vorbis_ValidBlockSize(UInt32 blockSize) {
|
static bool Vorbis_ValidBlockSize(UInt32 size) {
|
||||||
return blockSize >= 64 && blockSize <= 8192 && Math_IsPowOf2(blockSize);
|
return size >= 64 && size <= VORBIS_MAX_BLOCK_SIZE && Math_IsPowOf2(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ReturnCode Vorbis_DecodeHeader(struct VorbisState* ctx, UInt8 type) {
|
static ReturnCode Vorbis_DecodeHeader(struct VorbisState* ctx, UInt8 type) {
|
||||||
@ -1045,6 +1061,7 @@ static ReturnCode Vorbis_DecodeSetup(struct VorbisState* ctx) {
|
|||||||
result = Codebook_DecodeSetup(ctx, &ctx->Codebooks[i]);
|
result = Codebook_DecodeSetup(ctx, &ctx->Codebooks[i]);
|
||||||
if (result) return result;
|
if (result) return result;
|
||||||
}
|
}
|
||||||
|
ctx->NumCodebooks = count;
|
||||||
|
|
||||||
count = Vorbis_ReadBits(ctx, 6); count++;
|
count = Vorbis_ReadBits(ctx, 6); count++;
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
@ -1113,8 +1130,8 @@ ReturnCode Vorbis_DecodeHeaders(struct VorbisState* ctx) {
|
|||||||
if (result) return result;
|
if (result) return result;
|
||||||
|
|
||||||
/* window calculations can be pre-computed here */
|
/* window calculations can be pre-computed here */
|
||||||
UInt32 size = ctx->BlockSizes[0] + ctx->BlockSizes[1] * 4, offset = 0;
|
UInt32 count = ctx->BlockSizes[0] + ctx->BlockSizes[1] * 4, offset = 0;
|
||||||
ctx->WindowShort = Mem_Alloc(size, sizeof(Real32), "Vorbis windows");
|
ctx->WindowShort = Mem_Alloc(count, sizeof(Real32), "Vorbis windows");
|
||||||
Vorbis_CalcWindow(ctx, &offset, false, false, false);
|
Vorbis_CalcWindow(ctx, &offset, false, false, false);
|
||||||
|
|
||||||
ctx->WindowLong[0][0] = ctx->WindowShort + offset;
|
ctx->WindowLong[0][0] = ctx->WindowShort + offset;
|
||||||
@ -1126,6 +1143,10 @@ ReturnCode Vorbis_DecodeHeaders(struct VorbisState* ctx) {
|
|||||||
ctx->WindowLong[1][1] = ctx->WindowShort + offset;
|
ctx->WindowLong[1][1] = ctx->WindowShort + offset;
|
||||||
Vorbis_CalcWindow(ctx, &offset, true, true, true);
|
Vorbis_CalcWindow(ctx, &offset, true, true, true);
|
||||||
|
|
||||||
|
count = ctx->Channels * ctx->BlockSizes[1];
|
||||||
|
ctx->Values[0] = Mem_AllocCleared(count, sizeof(Real32), "Vorbis values");
|
||||||
|
ctx->Values[1] = Mem_AllocCleared(count, sizeof(Real32), "Vorbis values");
|
||||||
|
|
||||||
imdct_init(&ctx->imdct[0], ctx->BlockSizes[0]);
|
imdct_init(&ctx->imdct[0], ctx->BlockSizes[0]);
|
||||||
imdct_init(&ctx->imdct[1], ctx->BlockSizes[1]);
|
imdct_init(&ctx->imdct[1], ctx->BlockSizes[1]);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1155,9 +1176,13 @@ ReturnCode Vorbis_DecodeFrame(struct VorbisState* ctx) {
|
|||||||
next_window = Vorbis_ReadBits(ctx, 1);
|
next_window = Vorbis_ReadBits(ctx, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->Values = Mem_AllocCleared(ctx->Channels * ctx->CurBlockSize, sizeof(Real32), "audio values");
|
/* swap prev and cur outputs around */
|
||||||
|
Real32* tmp = ctx->Values[1]; ctx->Values[1] = ctx->Values[0]; ctx->Values[0] = tmp;
|
||||||
|
Mem_Set(ctx->Values[0], 0, ctx->Channels * ctx->CurBlockSize);
|
||||||
|
|
||||||
for (i = 0; i < ctx->Channels; i++) {
|
for (i = 0; i < ctx->Channels; i++) {
|
||||||
ctx->CurOutput[i] = ctx->Values + i * ctx->CurBlockSize;
|
ctx->CurOutput[i] = ctx->Values[0] + i * ctx->CurBlockSize;
|
||||||
|
ctx->PrevOutput[i] = ctx->Values[1] + i * ctx->PrevBlockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decode floor */
|
/* decode floor */
|
||||||
@ -1292,9 +1317,6 @@ Int32 Vorbis_OutputFrame(struct VorbisState* ctx, Int16* data) {
|
|||||||
|
|
||||||
finish:
|
finish:
|
||||||
ctx->PrevBlockSize = ctx->CurBlockSize;
|
ctx->PrevBlockSize = ctx->CurBlockSize;
|
||||||
for (i = 0; i < VORBIS_MAX_CHANS; i++) {
|
|
||||||
ctx->PrevOutput[i] = ctx->CurOutput[i];
|
|
||||||
}
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ struct VorbisState {
|
|||||||
struct Stream* Source; /* Source for filling Input buffer */
|
struct Stream* Source; /* Source for filling Input buffer */
|
||||||
|
|
||||||
UInt8 Channels, ModeNumBits;
|
UInt8 Channels, ModeNumBits;
|
||||||
UInt16 CurBlockSize, PrevBlockSize, DataSize;
|
UInt16 CurBlockSize, PrevBlockSize, DataSize, NumCodebooks;
|
||||||
Int32 SampleRate; Int32 BlockSizes[2];
|
Int32 SampleRate; Int32 BlockSizes[2];
|
||||||
Real32* Values;
|
Real32* Values[2]; /* swapped each frame */
|
||||||
Real32* PrevOutput[VORBIS_MAX_CHANS];
|
Real32* PrevOutput[VORBIS_MAX_CHANS];
|
||||||
Real32* CurOutput[VORBIS_MAX_CHANS];
|
Real32* CurOutput[VORBIS_MAX_CHANS];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user