using Amphora; using System; using System.IO; using System.Linq; using UnitTestSharp; using static Susurrus.UnitTests.TestSounds; namespace Susurrus.UnitTests { public class SoundDecoderTests : TestFixture { public const string OpusMessage = "This is an Ogg Opus file, but Susurrus loads only Ogg Vorbis and WAV. Convert it first with " + "python Scripts/convertaudio.py "; public const string Mp3Message = "This is an MP3 file, but Susurrus loads only Ogg Vorbis and WAV. Convert it first with " + "python Scripts/convertaudio.py "; public const string UnrecognizedMessage = "This isn't in an audio format Susurrus recognizes."; public static byte[] WavFile() { return WavDecoderTests.Riff(WavDecoderTests.Pcm16MonoFormat(), WavDecoderTests.Chunk("data", WavDecoderTests.ThreePcm16MonoFrames())); } public static byte[] NotAudio() { return WavDecoderTests.Ascii("This is just some text, not sound."); } public class DecodeBytesTests : TestFixture { public void DefaultView_Throws() { CheckThrow(typeof(ArgumentException)); SoundDecoder.Decode(default(ByteView)); } public void ViewOfALargerArray_SniffsAndDecodesOnlyTheWindow() { byte[] file = WavFile(); byte[] padded = new byte[file.Length + 30]; Array.Copy(file, 0, padded, 20, file.Length); DecodedSound sound = SoundDecoder.Decode(new ByteView(padded, startIndex: 20, endIndex: 20 + file.Length)).Value; CheckEqual(3, sound.FrameCount); } public void Wav_IsDecoded() { CheckEqual(3, DecodeAny(WavFile()).Value.FrameCount); } public void OggVorbis_IsDecoded() { CheckEqual(4410, DecodeAny(LoadFixture("Mono441Hz.ogg")).Value.FrameCount); } public void OggOpus_IsRejectedByName() { StatusOr result = DecodeAny(LoadFixture("OpusInOgg.ogg")); CheckEqual(SoundFailures.UnsupportedFormat, KindOf(result)); CheckEqual(OpusMessage, result.Status.Describe()); } public void Mp3_IsRejectedByName() { StatusOr result = DecodeAny(LoadFixture("Mp3WithoutTag.mp3")); CheckEqual(SoundFailures.UnsupportedFormat, KindOf(result)); CheckEqual(Mp3Message, result.Status.Describe()); } public void UnrecognizedBytes_AreRejectedAsUnrecognized() { StatusOr result = DecodeAny(NotAudio()); CheckEqual(SoundFailures.UnrecognizedFormat, KindOf(result)); CheckEqual(UnrecognizedMessage, result.Status.Describe()); } public void NoBytes_AreRejectedAsUnrecognized() { CheckEqual(SoundFailures.UnrecognizedFormat, KindOf(DecodeAny(new byte[0]))); } public void ABrokenWav_FailsWithTheWavDecodersFailure() { byte[] riffHeaderOnly = WavDecoderTests.Ascii("RIFF\0\0\0\0WAVE"); CheckEqual(SoundFailures.WavMalformed, KindOf(DecodeAny(riffHeaderOnly))); } public void ABrokenOgg_FailsWithTheOggDecodersFailure() { byte[] cutShort = OggDecoderTests.Truncated(LoadFixture("Mono441Hz.ogg"), 3000); CheckEqual(SoundFailures.OggFailed, KindOf(DecodeAny(cutShort))); } } public class DecodeStreamTests : TestFixture { public void NullStream_Throws() { CheckThrow(typeof(ArgumentNullException)); SoundDecoder.Decode((Stream)null); } public void SeekableWav_IsDecoded() { CheckEqual(3, SoundDecoder.Decode(new MemoryStream(WavFile())).Value.FrameCount); } public void SeekableOgg_IsDecoded() { using (Stream stream = OpenFixture("Mono441Hz.ogg")) { CheckEqual(4410, SoundDecoder.Decode(stream).Value.FrameCount); } } public void SeekableStreamStartingMidWay_DecodesFromItsPosition() { MemoryStream stream = new MemoryStream(new byte[7].Concat(WavFile()).ToArray()); stream.Position = 7; CheckEqual(3, SoundDecoder.Decode(stream).Value.FrameCount); } public void ForwardOnlyWav_IsDecoded() { CheckEqual(3, SoundDecoder.Decode(new TrickleStream(WavFile(), bytesPerRead: 1)).Value.FrameCount); } public void ForwardOnlyOgg_IsDecoded() { byte[] file = LoadFixture("Mono441Hz.ogg"); CheckEqual(4410, SoundDecoder.Decode(new TrickleStream(file, bytesPerRead: 200)).Value.FrameCount); } public void SeekableUnsupportedFormat_IsRejectedByName() { StatusOr result = SoundDecoder.Decode(new MemoryStream(LoadFixture("OpusInOgg.ogg"))); CheckEqual(SoundFailures.UnsupportedFormat, KindOf(result)); CheckEqual(OpusMessage, result.Status.Describe()); } public void ForwardOnlyUnsupportedFormat_IsRejectedByName() { StatusOr result = SoundDecoder.Decode(new TrickleStream(LoadFixture("OpusInOgg.ogg"), bytesPerRead: 50)); CheckEqual(SoundFailures.UnsupportedFormat, KindOf(result)); CheckEqual(OpusMessage, result.Status.Describe()); } public void SeekableUnrecognizedBytes_AreRejectedAsUnrecognized() { StatusOr result = SoundDecoder.Decode(new MemoryStream(NotAudio())); CheckEqual(SoundFailures.UnrecognizedFormat, KindOf(result)); CheckEqual(UnrecognizedMessage, result.Status.Describe()); } public void ForwardOnlyUnrecognizedBytes_AreRejectedAsUnrecognized() { StatusOr result = SoundDecoder.Decode(new TrickleStream(NotAudio(), bytesPerRead: 5)); CheckEqual(SoundFailures.UnrecognizedFormat, KindOf(result)); CheckEqual(UnrecognizedMessage, result.Status.Describe()); } } } }