/* initialize the dither structure */ public StereoDither_TPDF( NumBitsType Precision) { this.Left.Seed1 = new ParkAndMiller(1); this.Left.Seed2 = new ParkAndMiller(2); this.Right.Seed1 = new ParkAndMiller(3); this.Right.Seed2 = new ParkAndMiller(4); switch (Precision) { default: Debug.Assert(false); throw new ArgumentException(); case NumBitsType.eSample8bit: this.Left.Scale1 = .5f / SampConv.FLOATFACTOR8BIT; this.Left.Scale2 = .25f / SampConv.FLOATFACTOR8BIT; break; case NumBitsType.eSample16bit: this.Left.Scale1 = .5f / SampConv.FLOATFACTOR16BIT; this.Left.Scale2 = .25f / SampConv.FLOATFACTOR16BIT; break; case NumBitsType.eSample24bit: // shouldn't bother dithering for 24 bits Debug.Assert(false); throw new ArgumentException(); } this.Right.Scale1 = this.Left.Scale1; this.Right.Scale2 = this.Left.Scale2; }
public static OutputGeneric<T, WaveTableTestGeneratorParams<T, W>, W> Do( string baseName, GetDestinationMethod<T> getDestination, CreateDestinationHandlerMethod<T, W> createDestinationHandler, W destinationHandlerArguments, GeneratorMainLoopMethod<T, WaveTableTestGeneratorParams<T, W>, W> generatorMainLoop, WaveTableTestGeneratorParams<T, W> generatorParams, GeneratorCompletionMethod<WaveTableTestGeneratorParams<T, W>> generatorCompletion, IMainWindowServices mainWindow, NumChannelsType channels, NumBitsType bits, int samplingRate, int oversamplingFactor, bool showProgressWindow, bool modal) { // prerequisites return OutputGeneric<T, WaveTableTestGeneratorParams<T, W>, W>.Do( baseName, getDestination, createDestinationHandler, destinationHandlerArguments, generatorMainLoop, generatorParams, generatorCompletion, channels, bits, samplingRate, oversamplingFactor, showProgressWindow, modal); }
public AIFFWriter( Stream outputStream, NumChannelsType channels, NumBitsType bits, int samplingRate) { this.outputStream = outputStream; this.start = outputStream.Position; this.channels = channels; this.bits = bits; this.samplingRate = samplingRate; switch (bits) { default: Debug.Assert(false); throw new InvalidOperationException(); case NumBitsType.eSample8bit: expander = Expander_8; bytesPerPoint = 1; break; case NumBitsType.eSample16bit: expander = Expander_16; bytesPerPoint = 2; break; case NumBitsType.eSample24bit: expander = Expander_24; bytesPerPoint = 3; break; } switch (channels) { default: Debug.Assert(false); throw new InvalidOperationException(); case NumChannelsType.eSampleMono: pointsPerFrame = 1; break; case NumChannelsType.eSampleStereo: pointsPerFrame = 2; break; } SetUpAIFFHeader( outputStream, channels, bits, samplingRate); }
public static DestinationHandler <OutputSelectableFileDestination> CreateOutputSelectableFileDestinationHandler( OutputSelectableFileDestination destination, NumChannelsType channels, NumBitsType bits, int samplingRate, OutputSelectableFileArguments arguments) { return(new OutputSelectableFileDestinationHandler( destination.path, channels, bits, samplingRate, arguments)); }
public WaveTableTestGeneratorParams( WaveTableStorageRec data, double attack, double decay, NumBitsType numBits, int samplingRate, double frequency) { this.data = data; this.attack = attack; this.decay = decay; this.numBits = numBits; this.samplingRate = samplingRate; this.frequency = frequency; }
bool IMenuStripManagerHandler.ExecuteMenuItem(MenuStripManager menuStrip, ToolStripMenuItem menuItem) { if (menuItem == menuStrip.buildObjectToolStripMenuItem) { BuildThis(true /*force*/); return(true); } else if (menuItem == menuStrip.disassembleToolStripMenuItem) { DisassembleThis(); return(true); } else if (menuItem == menuStrip.openAsSampleToolStripMenuItem) { if (BuildThis(false /*force*/)) { NumBitsType numBits = NumBitsType.Max; float[] buffer = (float[])algoSampObject.SampleData.Buffer.Clone(); SampConv.QuantizeAndClampVector(buffer, numBits); // ensure target bit depth is honored SampleObjectRec sampleObject = new SampleObjectRec( mainWindow.Document, buffer, algoSampObject.SampleData.NumFrames, numBits, algoSampObject.NumChannels, algoSampObject.Origin, algoSampObject.LoopStart1, algoSampObject.LoopStart2, algoSampObject.LoopStart3, algoSampObject.LoopEnd1, algoSampObject.LoopEnd2, algoSampObject.LoopEnd3, algoSampObject.SamplingRate, algoSampObject.NaturalFrequency); sampleObject.Name = String.Format("Copy of {0}", algoSampObject.Name); mainWindow.Document.SampleList.Add(sampleObject); new SampleWindow(registration, sampleObject, mainWindow).Show(); } return(true); } else if (menuItem == menuStrip.deleteObjectToolStripMenuItem) { Close(); mainWindow.DeleteObject(algoSampObject, mainWindow.Document.AlgoSampList); return(true); } return(false); }
public static OutputGeneric <T, SynthesizerGeneratorParams <T, W>, W> Do( string baseName, GetDestinationMethod <T> getDestination, CreateDestinationHandlerMethod <T, W> createDestinationHandler, W destinationHandlerArguments, GeneratorMainLoopMethod <T, SynthesizerGeneratorParams <T, W>, W> generatorMainLoop, SynthesizerGeneratorParams <T, W> generatorParams, GeneratorCompletionMethod <SynthesizerGeneratorParams <T, W> > generatorCompletion, IMainWindowServices mainWindow, NumChannelsType channels, NumBitsType bits, int samplingRate, int oversamplingFactor, bool showProgressWindow, bool modal) { // prerequisites /* force an auto-save since play may take a long time */ MainWindow.DoAutosaveGlobally(); /* make sure all objects are up to date */ if (!mainWindow.MakeUpToDate()) { /* couldn't compile score elements */ return(null); } return(OutputGeneric <T, SynthesizerGeneratorParams <T, W>, W> .Do( baseName, getDestination, createDestinationHandler, destinationHandlerArguments, generatorMainLoop, generatorParams, generatorCompletion, channels, bits, samplingRate, oversamplingFactor, showProgressWindow, modal)); }
public SynthesizerGeneratorParams( IMainWindowServices mainWindow, Document document, List <TrackObjectRec> listOfTracks, TrackObjectRec keyTrack, int frameToStartAt, int samplingRate, int envelopeRate, NumChannelsType channels, LargeBCDType defaultBeatsPerMinute, double overallVolumeScalingReciprocal, LargeBCDType scanningGap, NumBitsType bits, bool clipWarn, int oversamplingFactor, bool showSummary, bool deterministic,// now ignored - control by setting randomSeed to null or int int?randomSeed, Synthesizer.AutomationSettings automationSettings) { this.mainWindow = mainWindow; this.document = document; this.listOfTracks = listOfTracks; this.keyTrack = keyTrack; this.frameToStartAt = frameToStartAt; this.samplingRate = samplingRate; this.envelopeRate = envelopeRate; this.channels = channels; this.defaultBeatsPerMinute = defaultBeatsPerMinute; this.overallVolumeScalingReciprocal = overallVolumeScalingReciprocal; this.scanningGap = scanningGap; this.bits = bits; this.clipWarn = clipWarn; this.oversamplingFactor = oversamplingFactor; this.showSummary = showSummary; this.deterministic = deterministic; this.randomSeed = randomSeed; this.automationSettings = automationSettings; }
public static void QuantizeAndClampVector(float[] vector, NumBitsType bits) { switch (bits) { default: Debug.Assert(false); throw new InvalidOperationException(); case NumBitsType.eSample8bit: for (int i = 0; i < vector.Length; i++) { float v = vector[i]; float v2 = SignedByteToFloat(FloatToSignedByte(vector[i])); Debug.Assert(v2 == SignedByteToFloat(FloatToSignedByte(vector[i]))); // verify conversion idempotency (i.e. stability) vector[i] = v2; } break; case NumBitsType.eSample16bit: for (int i = 0; i < vector.Length; i++) { float v = vector[i]; float v2 = SignedShortToFloat(FloatToSignedShort(vector[i])); Debug.Assert(v2 == SignedShortToFloat(FloatToSignedShort(vector[i]))); // verify conversion idempotency (i.e. stability) vector[i] = v2; } break; case NumBitsType.eSample24bit: for (int i = 0; i < vector.Length; i++) { float v = vector[i]; float v2 = SignedTribyteToFloat(FloatToSignedTribyte(vector[i])); Debug.Assert(v2 == SignedTribyteToFloat(FloatToSignedTribyte(vector[i]))); // verify conversion idempotency (i.e. stability) vector[i] = v2; } break; } }
public OutputSelectableFileDestinationHandler( string destinationPath, NumChannelsType channels, NumBitsType bits, int samplingRate, OutputSelectableFileArguments arguments) { outputStream = new FileStream( destinationPath, FileMode.Create, FileAccess.ReadWrite, FileShare.None, Constants.BufferSize); switch (Path.GetExtension(destinationPath).ToLowerInvariant()) { default: Debug.Assert(false); throw new ArgumentException(); case ".wav": outputWriter = new WAVWriter( outputStream, channels, bits, samplingRate); break; case ".aif": case ".aiff": outputWriter = new AIFFWriter( outputStream, channels, bits, samplingRate); break; } }
public Source(Document document) { _document = document; _SamplingRate = document.SamplingRate; _EnvelopeUpdateRate = document.EnvelopeUpdateRate; _Oversampling = document.Oversampling; _DefaultBeatsPerMinute = (LargeBCDType)document.DefaultBeatsPerMinute; _OverallVolumeScalingFactor = (LargeBCDType)document.OverallVolumeScalingFactor; _OutputNumBits = document.OutputNumBits; _ScanningGap = (LargeBCDType)document.ScanningGap; _BufferDuration = (LargeBCDType)document.BufferDuration; _ClipWarning = document.ClipWarning; _NumChannels = document.NumChannels; _ShowSummary = document.ShowSummary; _Deterministic = document.Deterministic; _Seed = document.Seed; foreach (TrackObjectRec Track in document.TrackList) { IncludedTracks.Add(new TrackInclusionRec(Track, this)); } document.TrackList.ListChanged += TrackList_ListChanged; }
/* RIFF file format, with WAVE information */ /* 'RIFF' */ /* 4-byte little endian length descriptor (minus 8 bytes for these 2 fields) */ /* 'WAVE' */ /* 'fmt ' */ /* 4-byte little endian length descriptor for the 'fmt ' header block */ /* - this should be 16. if not, then it's some other kind of WAV file */ /* 2-byte little endian format descriptor. this is always here. */ /* - 1 = PCM */ /* for future use: */ /* - 3 = IEEE floats */ /* and just in case: */ /* - 6 = 8-bit ITU-T G.711 A-law */ /* - 7 = 8-bit ITU-T G.711 mu-law */ /* - 0xFFFE = extensible (requires SubFormat field) */ /* 2-byte little endian number of channels. */ /* 4-byte little endian sampling rate integer. */ /* 4-byte little endian average bytes per second. */ /* 2-byte little endian block align. for 8-bit mono, this is 1; for 16-bit */ /* stereo, this is 4. */ /* 2-byte little endian number of bits. */ /* - 8 = 8-bit */ /* - 16 = 16-bit */ /* - 24 = 24-bit */ /* 'data' */ /* 4-byte little endian length of sample data descriptor */ /* any length data. 8-bit data goes from 0..255, but 16-bit data goes */ /* from -32768 to 32767. */ private static void SetUpWAVHeader( Stream outputStream, NumChannelsType channels, NumBitsType bits, int samplingRate) { using (BinaryWriter writer = new BinaryWriter(outputStream)) { int bytesPerSecond; short blockAlignment; /* 'RIFF' */ writer.WriteFixedStringASCII(4, "RIFF"); /* figure out how long chunk will be */ switch (bits) { default: Debug.Assert(false); throw new ArgumentException(); case NumBitsType.eSample8bit: switch (channels) { default: Debug.Assert(false); throw new ArgumentException(); case NumChannelsType.eSampleMono: bytesPerSecond = samplingRate * 1; blockAlignment = 1; break; case NumChannelsType.eSampleStereo: bytesPerSecond = samplingRate * 2; blockAlignment = 2; break; } break; case NumBitsType.eSample16bit: switch (channels) { default: Debug.Assert(false); throw new ArgumentException(); case NumChannelsType.eSampleMono: bytesPerSecond = samplingRate * 2; blockAlignment = 2; break; case NumChannelsType.eSampleStereo: bytesPerSecond = samplingRate * 4; blockAlignment = 4; break; } break; case NumBitsType.eSample24bit: switch (channels) { default: Debug.Assert(false); throw new ArgumentException(); case NumChannelsType.eSampleMono: bytesPerSecond = samplingRate * 3; blockAlignment = 3; break; case NumChannelsType.eSampleStereo: bytesPerSecond = samplingRate * 6; blockAlignment = 6; break; } break; } /* 4-byte little endian length descriptor (minus 8 bytes for these 2 fields) */ writer.WriteInt32(0); // placeholder - corrected later /* 'WAVE' */ writer.WriteFixedStringASCII(4, "WAVE"); /* 'fmt ' */ writer.WriteFixedStringASCII(4, "fmt "); /* 4-byte little endian length descriptor for the 'fmt ' header block */ /* - this should be 16. if not, then it's some other kind of WAV file */ writer.WriteInt32(16); /* 2-byte little endian format descriptor. this is always here. */ /* - 1 = PCM */ writer.WriteInt16(1); /* 2-byte little endian number of channels. */ switch (channels) { default: Debug.Assert(false); throw new ArgumentException(); case NumChannelsType.eSampleMono: writer.WriteInt16(1); break; case NumChannelsType.eSampleStereo: writer.WriteInt16(2); break; } /* 4-byte little endian sampling rate integer. */ writer.WriteInt32(samplingRate); /* 4-byte little endian average bytes per second. */ writer.WriteInt32(bytesPerSecond); /* 2-byte little endian block align. for 8-bit mono, this is 1; for 16-bit */ /* stereo, this is 4. */ writer.WriteInt16(blockAlignment); /* 2-byte little endian number of bits. */ /* - 8 = 8-bit */ /* - 16 = 16-bit */ /* - 24 = 24-bit */ switch (bits) { default: Debug.Assert(false); throw new ArgumentException(); case NumBitsType.eSample8bit: writer.WriteInt16(8); break; case NumBitsType.eSample16bit: writer.WriteInt16(16); break; case NumBitsType.eSample24bit: writer.WriteInt16(24); break; } /* 'data' */ writer.WriteFixedStringASCII(4, "data"); /* 4-byte little endian length of sample data descriptor */ writer.WriteInt32(0); // placeholder - corrected later /* any length data. 8-bit data goes from 0..255, but 16-bit data goes */ /* from -32768 to 32767. */ } }
/* RIFF file format, with WAVE information */ /* 'RIFF' */ /* 4-byte little endian length descriptor (minus 8 bytes for these 2 fields) */ /* 'WAVE' */ /* 'fmt ' */ /* 4-byte little endian length descriptor for the 'fmt ' header block */ /* - this should be 16. if not, then it's some other kind of WAV file */ /* 2-byte little endian format descriptor. this is always here. */ /* - 1 = PCM */ /* 2-byte little endian number of channels. */ /* 4-byte little endian sampling rate integer. */ /* 4-byte little endian average bytes per second. */ /* 2-byte little endian block align. for 8-bit mono, this is 1; for 16-bit */ /* stereo, this is 4. */ /* 2-byte little endian number of bits. */ /* - 8 = 8-bit */ /* - 16 = 16-bit */ /* - 24 = 24-bit */ /* 'data' */ /* 4-byte little endian length of sample data descriptor */ /* any length data. 8-bit data goes from 0..255, but 16-bit data goes */ /* from -32768 to 32767. */ public static void ReadPreamble( Stream stream, out NumBitsType numBitsOut, out NumChannelsType numChannelsOut, out int numSampleFramesOut, out int samplingRateOut) { NumBitsType numBits; NumChannelsType numChannels; int numSampleFrames; int samplingRate; long audioDataOffset; numBitsOut = (NumBitsType)0; numChannelsOut = (NumChannelsType)0; numSampleFramesOut = 0; samplingRateOut = 0; try { using (BinaryReader File = new BinaryReader(stream)) { string stringBuffer; /* 'RIFF' */ stringBuffer = File.ReadFixedStringASCII(4); if (!String.Equals(stringBuffer, "RIFF")) { throw new AudioFileReaderException(AudioFileReaderErrors.UnrecognizedFileFormat); } /* 4-byte little endian length descriptor (minus 8 bytes for these 2 fields) */ int totalFileLength = File.ReadInt32(); /* 'WAVE' */ stringBuffer = File.ReadFixedStringASCII(4); if (!String.Equals(stringBuffer, "WAVE")) { throw new AudioFileReaderException(AudioFileReaderErrors.UnrecognizedFileFormat); } /* 'fmt ' */ stringBuffer = File.ReadFixedStringASCII(4); if (!String.Equals(stringBuffer, "fmt ")) { throw new AudioFileReaderException(AudioFileReaderErrors.UnrecognizedFileFormat); } /* 4-byte little endian length descriptor for the 'fmt ' header block */ /* - this should be 16. if not, then it's some other kind of WAV file */ int headerLength = File.ReadInt32(); if (headerLength != 16) { throw new AudioFileReaderException(AudioFileReaderErrors.UnrecognizedFileFormat); } /* 2-byte little endian format descriptor. this is always here. */ /* - 1 = PCM */ short dataTypeDescriptor = File.ReadInt16(); if (dataTypeDescriptor != 1) { throw new AudioFileReaderException(AudioFileReaderErrors.NotUncompressedPCM); } /* 2-byte little endian number of channels. */ short numberOfChannelsRaw = File.ReadInt16(); if ((numberOfChannelsRaw != 1) && (numberOfChannelsRaw != 2)) { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedNumberOfChannels); } /* 4-byte little endian sampling rate integer. */ samplingRate = File.ReadInt32(); /* 4-byte little endian average bytes per second. */ int averageBytesPerSecond = File.ReadInt32(); /* 2-byte little endian block align. for 8-bit mono, this is 1; for 16-bit */ /* stereo, this is 4. */ short blockAlignment = File.ReadInt16(); /* 2-byte little endian number of bits. */ /* - 8 = 8-bit */ /* - 16 = 16-bit */ /* - 24 = 24-bit */ short numberOfBitsRaw = File.ReadInt16(); switch (numberOfBitsRaw) { default: throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedNumberOfBits); case 8: numBits = NumBitsType.eSample8bit; break; case 16: numBits = NumBitsType.eSample16bit; break; case 24: numBits = NumBitsType.eSample24bit; break; } /* 'data' */ stringBuffer = File.ReadFixedStringASCII(4); if (!String.Equals(stringBuffer, "data")) { throw new AudioFileReaderException(AudioFileReaderErrors.UnrecognizedFileFormat); } /* 4-byte little endian length of sample data descriptor */ int sampledNumberOfBytes = File.ReadInt32(); audioDataOffset = stream.Position; /* calculate number of sample frames */ switch (numBits) { default: Debug.Assert(false); throw new InvalidOperationException(); case NumBitsType.eSample8bit: switch (numberOfChannelsRaw) { default: Debug.Assert(false); throw new InvalidOperationException(); case 1: numSampleFrames = sampledNumberOfBytes / 1; break; case 2: numSampleFrames = sampledNumberOfBytes / 2; break; } break; case NumBitsType.eSample16bit: switch (numberOfChannelsRaw) { default: Debug.Assert(false); throw new InvalidOperationException(); case 1: numSampleFrames = sampledNumberOfBytes / 2; break; case 2: numSampleFrames = sampledNumberOfBytes / 4; break; } break; case NumBitsType.eSample24bit: switch (numberOfChannelsRaw) { default: Debug.Assert(false); throw new InvalidOperationException(); case 1: numSampleFrames = sampledNumberOfBytes / 3; break; case 2: numSampleFrames = sampledNumberOfBytes / 6; break; } break; } /* any length data. 8-bit data goes from 0..255, but 16-bit data goes */ /* from -32768 to 32767. */ switch (numberOfChannelsRaw) { default: Debug.Assert(false); throw new InvalidOperationException(); case 1: numChannels = NumChannelsType.eSampleMono; break; case 2: numChannels = NumChannelsType.eSampleStereo; break; } } } catch (InvalidDataException) { throw new AudioFileReaderException(AudioFileReaderErrors.InvalidData); } numBitsOut = numBits; numChannelsOut = numChannels; numSampleFramesOut = numSampleFrames; samplingRateOut = samplingRate; stream.Seek(audioDataOffset, SeekOrigin.Begin); }
/* this routine asks for a file and tries to import the contents of that */ /* file as an AIFF sample. it reports any errors to the user. */ public static bool ImportAIFFSample( Registration registration, IMainWindowServices mainWindow, out int index) { index = -1; string path; using (OpenFileDialog dialog = new OpenFileDialog()) { dialog.Title = "Import AIFF Sample"; dialog.Filter = "AIFF Audio File (.aif, .aiff)|*.aif;*.aiff|Any File Type (*)|*"; DialogResult result = dialog.ShowDialog(); if (result != DialogResult.OK) { return(false); } path = dialog.FileName; } using (Stream input = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, Constants.BufferSize)) { try { using (AudioFileReader reader = new AIFFReader(input, true /*allowTruncated*/)) { NumBitsType numBits = reader.NumBits; NumChannelsType numChannels = reader.NumChannels; int numFrames = reader.NumFrames; int samplingRate = reader.SamplingRate; float[] sampleData; try { sampleData = new float[(numFrames + 1) * reader.PointsPerFrame]; } catch (OutOfMemoryException) { throw new AudioFileReaderException(AudioFileReaderErrors.OutOfMemory); } reader.ReadPoints(sampleData, 0, numFrames * reader.PointsPerFrame); if (reader.Truncated) { const string ErrorTooShort = "The file appears to be incomplete. Appending silence to end of sample data."; MessageBox.Show(ErrorTooShort, "Import Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } SampleObjectRec ReturnedSampleObject = new SampleObjectRec( mainWindow.Document, sampleData, numFrames, numBits, numChannels, 0, 0, 0, 0, 0, 0, 0, samplingRate, Constants.MIDDLEC); ReturnedSampleObject.Name = Path.GetFileName(path); index = mainWindow.Document.SampleList.Count; mainWindow.Document.SampleList.Add(ReturnedSampleObject); new SampleWindow(registration, ReturnedSampleObject, mainWindow).Show(); return(true); } } catch (AudioFileReaderException exception) { MessageBox.Show(AudioFileReaderException.MessageFromError(exception.Error), "Import Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } return(false); }
/* AIFF/AIFF-C File Format: */ /* "FORM" */ /* 4-byte big endian form chunk length descriptor (minus 8 for "FORM" & this) */ /* 4-byte type */ /* "AIFF" = AIFF format file */ /* "AIFC" = AIFF-C format file */ /* in any order, these chunks can occur: */ /* Version Chunk (this only occurs in AIFF-C files) */ /* "FVER" */ /* 4-byte big endian length, which should always be the value 4 (four) */ /* 4-byte date code. this is probably 0xA2805140 (stored big endian), but it */ /* probably doesn't matter. */ /* Common Chunk for AIFF files */ /* "COMM" */ /* 4-byte big endian length. */ /* always 18 for AIFF files */ /* 2-byte big endian number of channels */ /* 4-byte big endian number of sample frames */ /* 2-byte big endian number of bits per sample */ /* a value in the domain 1..32 */ /* 10-byte extended precision number of frames per second */ /* Common Chunk for AIFF-C files */ /* "COMM" */ /* 4-byte big endian length. */ /* 22 + compression method string length for AIFF-C files */ /* 2-byte big endian number of channels */ /* 4-byte big endian number of sample frames */ /* 2-byte big endian number of bits per sample */ /* a value in the domain 1..32 */ /* 10-byte extended precision number of frames per second */ /* 4-byte character code ID for the compression method */ /* "NONE" means there is no compression method used */ /* some characters in a string identifying the compression method */ /* this must be padded to an even number of bytes, but the pad is */ /* NOT included in the length descriptor for the chunk. */ /* for uncompressed data, the string should be */ /* "\x0enot compressed\x00", including the null, for 16 bytes. */ /* the total chunk length is thus 38 bytes. */ /* Sound Data Chunk */ /* "SSND" */ /* 4-byte big endian number of bytes in sample data array */ /* 4-byte big endian offset to the first byte of sample data in the array */ /* 4-byte big endian number of bytes to which the sound data is aligned. */ /* any length vector of raw sound data. */ /* this must be padded to an even number of bytes, but the pad is */ /* NOT included in the length descriptor for the chunk. */ /* Samples are stored in an integral number of bytes, the smallest that */ /* is required for the specified number of bits. If this is not an even */ /* multiple of 8, then the data is shifted left and the low bits are zeroed */ /* Multichannel sound is interleaved with the left channel first. */ private static void ReadPreamble( Stream stream, out NumBitsType numBitsOut, out NumChannelsType numChannelsOut, out int numSampleFramesOut, out int samplingRateOut) { NumBitsType numBits = (NumBitsType)(-1); bool numBitsIsValid = false; NumChannelsType numChannels = (NumChannelsType)(-1); bool numChannelsIsValid = false; int numSampleFrames = -1; bool numSampleFramesIsValid = false; int samplingRate = -1; bool samplingRateIsValid = false; long audioDataOffset = 0; bool rawDataFromFileIsValid = false; numBitsOut = (NumBitsType)0; numChannelsOut = (NumChannelsType)0; numSampleFramesOut = 0; samplingRateOut = 0; try { using (BinaryReader File = new BinaryReader(stream)) { string charBuff; /* "FORM" */ charBuff = File.ReadFixedStringASCII(4); if (!String.Equals(charBuff, "FORM")) { throw new AudioFileReaderException(AudioFileReaderErrors.UnrecognizedFileFormat); } /* 4-byte big endian form chunk length descriptor (minus 8 for "FORM" & this) */ int formChunkLength = File.ReadInt32BigEndian(); /* 4-byte type */ /* "AIFF" = AIFF format file */ /* "AIFC" = AIFF-C format file */ charBuff = File.ReadFixedStringASCII(4); bool isAIFFC; if (String.Equals(charBuff, "AIFF")) { isAIFFC = false; } else if (String.Equals(charBuff, "AIFC")) { isAIFFC = true; } else { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedVariant); } formChunkLength -= 4; /* now, read in chunks until we die */ while (formChunkLength > 0) { /* get the chunk type */ charBuff = File.ReadFixedStringASCII(4); /* get the chunk length */ int localChunkLength = File.ReadInt32BigEndian(); formChunkLength -= 8; /* adjust for even alignment */ if ((localChunkLength % 2) != 0) { localChunkLength += 1; } formChunkLength -= localChunkLength; /* decode the chunk */ if (String.Equals(charBuff, "COMM")) { uint exponent; uint mantissa; byte[] extended = new byte[10]; if (!isAIFFC) { short s; /* Common Chunk for AIFF files */ /* "COMM" */ /* 4-byte big endian length. */ /* always 18 for AIFF files */ if (localChunkLength != 18) { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedVariant); } /* 2-byte big endian number of channels */ s = File.ReadInt16BigEndian(); switch (s) { default: throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedNumberOfChannels); case 1: numChannels = NumChannelsType.eSampleMono; numChannelsIsValid = true; break; case 2: numChannels = NumChannelsType.eSampleStereo; numChannelsIsValid = true; break; } /* 4-byte big endian number of sample frames */ numSampleFrames = File.ReadInt32BigEndian(); numSampleFramesIsValid = true; /* 2-byte big endian number of bits per sample */ /* a value in the domain 1..32 */ s = File.ReadInt16BigEndian(); switch (s) { default: throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedNumberOfBits); case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: numBits = NumBitsType.eSample8bit; numBitsIsValid = true; break; case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: numBits = NumBitsType.eSample16bit; numBitsIsValid = true; break; case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: numBits = NumBitsType.eSample24bit; numBitsIsValid = true; break; } /* 10-byte extended precision number of frames per second */ File.ReadRaw(extended, 0, 10); } else { short s; /* Common Chunk for AIFF-C files */ /* "COMM" */ /* 4-byte big endian length. */ /* always 18 for AIFF files */ if (localChunkLength < 22) { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedVariant); } /* 2-byte big endian number of channels */ s = File.ReadInt16BigEndian(); switch (s) { default: throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedNumberOfChannels); case 1: numChannels = NumChannelsType.eSampleMono; numChannelsIsValid = true; break; case 2: numChannels = NumChannelsType.eSampleStereo; numChannelsIsValid = true; break; } /* 4-byte big endian number of sample frames */ numSampleFrames = File.ReadInt32BigEndian(); numSampleFramesIsValid = true; /* 2-byte big endian number of bits per sample */ /* a value in the domain 1..32 */ s = File.ReadInt16BigEndian(); switch (s) { default: throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedNumberOfBits); case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: numBits = NumBitsType.eSample8bit; numBitsIsValid = true; break; case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: numBits = NumBitsType.eSample16bit; numBitsIsValid = true; break; case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: numBits = NumBitsType.eSample24bit; numBitsIsValid = true; break; } /* 10-byte extended precision number of frames per second */ File.ReadRaw(extended, 0, 10); /* 4-byte character code ID for the compression method */ /* "NONE" means there is no compression method used */ charBuff = File.ReadFixedStringASCII(4); if (!String.Equals(charBuff, "NONE")) { throw new AudioFileReaderException(AudioFileReaderErrors.NotUncompressedPCM); } /* some characters in a string identifying the compression method */ /* this must be padded to an even number of bytes, but the pad is */ /* NOT included in the length descriptor for the chunk. */ /* for uncompressed data, the string should be */ /* "\x0enot compressed\x00", including the null, for 16 bytes. */ /* the total chunk length is thus 38 bytes. */ for (int i = 0; i < localChunkLength - 22; i++) { File.ReadByte(); } } /* extended 22050 = 400D AC44000000000000 */ /* extended 22051 = 400D AC46000000000000 */ /* extended 44100 = 400E AC44000000000000 */ /* extended 44101 = 400E AC45000000000000 */ exponent = (((uint)extended[0] & 0xff) << 8) | ((uint)extended[1] & 0xff); mantissa = (((uint)extended[2] & 0xff) << 24) | (((uint)extended[3] & 0xff) << 16) | (((uint)extended[4] & 0xff) << 8) | ((uint)extended[5] & 0xff); samplingRate = (int)(mantissa >> (0x401e - (int)exponent)); if (samplingRate < Constants.MINSAMPLINGRATE) { samplingRate = Constants.MINSAMPLINGRATE; } if (samplingRate > Constants.MAXSAMPLINGRATE) { samplingRate = Constants.MAXSAMPLINGRATE; } samplingRateIsValid = true; } else if (String.Equals(charBuff, "SSND")) { /* Sound Data Chunk */ /* "SSND" */ /* 4-byte big endian number of bytes in sample data array */ /* only one of these is allowed */ if (rawDataFromFileIsValid) { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedVariant); } /* 4-byte big endian offset to the first byte of sample data in the array */ int offsetToFirstByte = File.ReadInt32BigEndian(); if (offsetToFirstByte != 0) { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedVariant); } /* 4-byte big endian number of bytes to which the sound data is aligned. */ int alignmentFactor = File.ReadInt32BigEndian(); if (alignmentFactor != 0) { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedVariant); } /* any length vector of raw sound data. */ /* this must be padded to an even number of bytes, but the pad is */ /* NOT included in the length descriptor for the chunk. */ /* Samples are stored in an integral number of bytes, the smallest that */ /* is required for the specified number of bits. If this is not an even */ /* multiple of 8, then the data is shifted left and the low bits are zeroed */ /* Multichannel sound is interleaved with the left channel first. */ if (stream.Length - stream.Position < localChunkLength - 8) { throw new AudioFileReaderException(AudioFileReaderErrors.Truncated); } rawDataFromFileIsValid = true; audioDataOffset = stream.Position; stream.Seek(localChunkLength - 8, SeekOrigin.Current); } else { /* just read the data & get rid of it */ while (localChunkLength > 0) { File.ReadByte(); localChunkLength -= 1; } } } } } catch (InvalidDataException) { throw new AudioFileReaderException(AudioFileReaderErrors.InvalidData); } if (!rawDataFromFileIsValid || !numBitsIsValid || !numChannelsIsValid || !samplingRateIsValid || !numSampleFramesIsValid) { throw new AudioFileReaderException(AudioFileReaderErrors.UnsupportedVariant); } numBitsOut = numBits; numChannelsOut = numChannels; numSampleFramesOut = numSampleFrames; samplingRateOut = samplingRate; stream.Seek(audioDataOffset, SeekOrigin.Begin); }
public static OutputGeneric <T, U, W> Do( string baseName, GetDestinationMethod <T> getDestination, CreateDestinationHandlerMethod <T, W> createDestinationHandler, W destinationHandlerParams, GeneratorMainLoopMethod <T, U, W> generatorMainLoop, U generatorParams, GeneratorCompletionMethod <U> generatorCompletion, NumChannelsType channels, NumBitsType bits, int samplingRate, int oversamplingFactor, bool showProgressWindow, bool modal) // modal is only meaningful when showProgressWindow==true { // set up processing record OutputGeneric <T, U, W> state = new OutputGeneric <T, U, W>(); state.channels = channels; state.bits = bits; state.samplingRate = samplingRate; state.oversamplingFactor = oversamplingFactor; state.totalSampleCount = 0; state.clippedSampleCount = 0; state.maxClipExtent = 0; state.oversamplingSkipCarryover = 0; if ((state.bits == NumBitsType.eSample8bit) || (state.bits == NumBitsType.eSample16bit)) { if (OutputGeneric <T, U, W> .UseHPTRI) // TODO: add dither selector to global settings { state.ditherState = new Synthesizer.StereoDither_HPTRI(bits); } else { state.ditherState = new Synthesizer.StereoDither_TPDF(bits); } } if (!getDestination(out state.destination)) { return(null); } state.createDestinationHandler = createDestinationHandler; state.generatorMainLoop = generatorMainLoop; state.generatorParams = generatorParams; state.generatorCompletion = generatorCompletion; state.destinationHandlerParams = destinationHandlerParams; state.stopper = new Synthesizer.StopTask(); state.waitFinishedHelper = new WaitFinishedHelper(); // All synth parameter initialization must be done by this point to avoid race conditions!!! state.thread = new Thread(ThreadMain); state.thread.Start(state); if (showProgressWindow) { state.progressWindow = new OutputProgressWindow( baseName, true /*show clipping*/, state, state, state.stopper, state.waitFinishedHelper, state.waitFinishedHelper, delegate() { ClipInfo clipInfo = new ClipInfo( state.totalSampleCount, state.clippedSampleCount, state.maxClipExtent); state.generatorCompletion( generatorParams, ref clipInfo); }); if (modal) { state.progressWindow.ShowDialog(); state.Dispose(); // suppress finalize } else { state.progressWindow.Show(); // client required to dispose after completion } } // After this, the dialog prevents UI interaction with the application on the main thread // and the rendering thread does it's thing until finished. // The dialog and the rendering thread talk to each other about stopping and completion. return(state); }
/* AIFF/AIFF-C File Format: */ /* "FORM" */ /* 4-byte big endian form chunk length descriptor (minus 8 for "FORM" & this) */ /* 4-byte type */ /* "AIFF" = AIFF format file */ /* "AIFC" = AIFF-C format file */ /* in any order, these chunks can occur: */ /* Version Chunk (this only occurs in AIFF-C files) */ /* "FVER" */ /* 4-byte big endian length, which should always be the value 4 (four) */ /* 4-byte date code. this is probably 0xA2805140 (stored big endian), but it */ /* probably doesn't matter. */ /* Common Chunk for AIFF files */ /* "COMM" */ /* 4-byte big endian length. */ /* always 18 for AIFF files */ /* 2-byte big endian number of channels */ /* 4-byte big endian number of sample frames */ /* 2-byte big endian number of bits per sample */ /* a value in the domain 1..32 */ /* 10-byte extended precision number of frames per second */ /* Common Chunk for AIFF-C files */ /* "COMM" */ /* 4-byte big endian length. */ /* 22 + compression method string length for AIFF-C files */ /* 2-byte big endian number of channels */ /* 4-byte big endian number of sample frames */ /* 2-byte big endian number of bits per sample */ /* a value in the domain 1..32 */ /* 10-byte extended precision number of frames per second */ /* 4-byte character code ID for the compression method */ /* "NONE" means there is no compression method used */ /* some characters in a string identifying the compression method */ /* this must be padded to an even number of bytes, but the pad is */ /* NOT included in the length descriptor for the chunk. */ /* for uncompressed data, the string should be */ /* "\x0enot compressed\x00", including the null, for 16 bytes. */ /* the total chunk length is thus 38 bytes. */ /* Sound Data Chunk */ /* "SSND" */ /* 4-byte big endian number of bytes in sample data array */ /* 4-byte big endian offset to the first byte of sample data in the array */ /* 4-byte big endian number of bytes to which the sound data is aligned. */ /* any length vector of raw sound data. */ /* this must be padded to an even number of bytes, but the pad is */ /* NOT included in the length descriptor for the chunk. */ /* Samples are stored in an integral number of bytes, the smallest that */ /* is required for the specified number of bits. If this is not an even */ /* multiple of 8, then the data is shifted left and the low bits are zeroed */ /* Multichannel sound is interleaved with the left channel first. */ private static void SetUpAIFFHeader( Stream outputStream, NumChannelsType channels, NumBitsType bits, int samplingRate) { using (BinaryWriter writer = new BinaryWriter(outputStream)) { /* 0..3 */ /* "FORM" */ writer.WriteFixedStringASCII(4, "FORM"); /* 4..7 */ /* 4-byte big endian form chunk length descriptor (minus 8 for "FORM" & this) */ writer.WriteInt32BigEndian(0); /* RESOLVED LATER */ /* 8..11 */ /* 4-byte type */ /* "AIFC" = AIFF-C format file */ writer.WriteFixedStringASCII(4, "AIFF"); /* 12..15 */ /* "COMM" */ writer.WriteFixedStringASCII(4, "COMM"); /* 16..19 */ /* 4-byte big endian length. */ /* always 18 for AIFF files */ writer.WriteInt32BigEndian(18); /* 20..21 */ /* 2-byte big endian number of channels */ writer.WriteInt16BigEndian(channels == NumChannelsType.eSampleStereo ? (short)2 : (short)1); /* 22..25 */ /* 4-byte big endian number of sample frames */ writer.WriteInt32BigEndian(0); /* RESOLVED LATER */ /* 26..27 */ /* 2-byte big endian number of bits per sample */ /* a value in the domain 1..32 */ switch (bits) { default: Debug.Assert(false); throw new ArgumentException(); case NumBitsType.eSample8bit: writer.WriteInt16BigEndian(8); break; case NumBitsType.eSample16bit: writer.WriteInt16BigEndian(16); break; case NumBitsType.eSample24bit: writer.WriteInt16BigEndian(24); break; } /* 28..37 */ /* 10-byte extended precision number of frames per second */ /* extended 22050 = 400D AC44000000000000 */ /* extended 22051 = 400D AC46000000000000 */ /* extended 44100 = 400E AC44000000000000 */ /* extended 44101 = 400E AC45000000000000 */ uint exponent = 0x401e; uint mantissa = (uint)samplingRate; while ((mantissa & 0x80000000) == 0) { mantissa = mantissa << 1; exponent -= 1; } byte[] extended = new byte[10]; extended[0] = (byte)((exponent >> 8) & 0xff); extended[1] = (byte)(exponent & 0xff); extended[2] = (byte)((mantissa >> 24) & 0xff); extended[3] = (byte)((mantissa >> 16) & 0xff); extended[4] = (byte)((mantissa >> 8) & 0xff); extended[5] = (byte)(mantissa & 0xff); extended[6] = 0; extended[7] = 0; extended[8] = 0; extended[9] = 0; writer.WriteRaw(extended, 0, extended.Length); /* 38..41 */ /* "SSND" */ writer.WriteFixedStringASCII(4, "SSND"); /* 42..45 */ /* 4-byte big endian number of bytes in sample data array */ writer.WriteInt32BigEndian(0); /* RESOLVED LATER */ /* 46..49 */ /* 4-byte big endian offset to the first byte of sample data in the array */ writer.WriteInt32BigEndian(0); /* 50..53 */ /* 4-byte big endian number of bytes to which the sound data is aligned. */ writer.WriteInt32BigEndian(0); /* any length vector of raw sound data. */ /* this must be padded to an even number of bytes, but the pad is */ /* NOT included in the length descriptor for the chunk. */ /* Samples are stored in an integral number of bytes, the smallest that */ /* is required for the specified number of bits. If this is not an even */ /* multiple of 8, then the data is shifted left and the low bits are zeroed */ /* Multichannel sound is interleaved with the left channel first. */ } }
/* update various size fields in the file */ private static void ResolveAIFFHeader( Stream output, long start, int totalFrameCount, NumChannelsType channels, NumBitsType bits) { byte[] buffer = new byte[4]; int totalBytesOfSamples = totalFrameCount; if (channels == NumChannelsType.eSampleStereo) { totalBytesOfSamples *= 2; } switch (bits) { default: Debug.Assert(false); throw new ArgumentException(); case NumBitsType.eSample8bit: break; case NumBitsType.eSample16bit: totalBytesOfSamples *= 2; break; case NumBitsType.eSample24bit: totalBytesOfSamples *= 3; break; } /* make sure file is an even number of bytes */ if (((output.Position - start) & 1) != 0) { output.WriteByte(0); } /* chop off any crud from the end */ output.SetLength(output.Position); /* 4..7 */ /* 4-byte big endian form chunk length descriptor (minus 8 for "FORM" & this) */ output.Position = start + 4; buffer[0] = (byte)(((totalBytesOfSamples + 54 - 8) >> 24) & 0xff); buffer[1] = (byte)(((totalBytesOfSamples + 54 - 8) >> 16) & 0xff); buffer[2] = (byte)(((totalBytesOfSamples + 54 - 8) >> 8) & 0xff); buffer[3] = (byte)((totalBytesOfSamples + 54 - 8) & 0xff); output.Write(buffer, 0, 4); /* 22..25 */ /* 4-byte big endian number of sample frames */ output.Position = start + 22; buffer[0] = (byte)((totalFrameCount >> 24) & 0xff); buffer[1] = (byte)((totalFrameCount >> 16) & 0xff); buffer[2] = (byte)((totalFrameCount >> 8) & 0xff); buffer[3] = (byte)(totalFrameCount & 0xff); output.Write(buffer, 0, 4); /* 42..45 */ /* 4-byte big endian number of bytes in sample data array */ output.Position = start + 42; buffer[0] = (byte)(((totalBytesOfSamples + 8) >> 24) & 0xff); buffer[1] = (byte)(((totalBytesOfSamples + 8) >> 16) & 0xff); buffer[2] = (byte)(((totalBytesOfSamples + 8) >> 8) & 0xff); buffer[3] = (byte)((totalBytesOfSamples + 8) & 0xff); output.Write(buffer, 0, 4); output.Position = output.Length; }
/* update various size fields in the file */ private static void ResolveWAVHeader( Stream output, long start, int totalFrameCount, NumChannelsType channels, NumBitsType bits) { byte[] buffer = new byte[4]; int totalBytesOfSamples = totalFrameCount; if (channels == NumChannelsType.eSampleStereo) { totalBytesOfSamples *= 2; } switch (bits) { default: Debug.Assert(false); throw new ArgumentException(); case NumBitsType.eSample8bit: break; case NumBitsType.eSample16bit: totalBytesOfSamples *= 2; break; case NumBitsType.eSample24bit: totalBytesOfSamples *= 3; break; } /* make sure file is an even number of bytes */ if (((output.Position - start) & 1) != 0) { output.WriteByte(0); } /* chop off any crud from the end */ output.SetLength(output.Position); /* 4..7 */ /* 4-byte little endian length descriptor (minus 8 bytes for these 2 fields) */ output.Position = start + 4; buffer[0] = (byte)((totalBytesOfSamples + 36) & 0xff); buffer[1] = (byte)(((totalBytesOfSamples + 36) >> 8) & 0xff); buffer[2] = (byte)(((totalBytesOfSamples + 36) >> 16) & 0xff); buffer[3] = (byte)(((totalBytesOfSamples + 36) >> 24) & 0xff); output.Write(buffer, 0, 4); /* 40..43 */ /* 4-byte little endian length of sample data descriptor */ output.Position = start + 40; buffer[0] = (byte)(totalBytesOfSamples & 0xff); buffer[1] = (byte)((totalBytesOfSamples >> 8) & 0xff); buffer[2] = (byte)((totalBytesOfSamples >> 16) & 0xff); buffer[3] = (byte)((totalBytesOfSamples >> 24) & 0xff); output.Write(buffer, 0, 4); output.Position = output.Length; }