public int GetResampledData(GATData target, int targetLength, int offsetInTarget, double pitch) { double dLastIndex = _nextIndex + pitch * (targetLength - 1); int iLastIndex = ( int )dLastIndex;; int sign = System.Math.Sign(pitch); if (dLastIndex - ( double )iLastIndex > 0d) { iLastIndex += sign; } if (iLastIndex >= _data.Count - 1) { targetLength = ( int )((( double )(_data.Count - 1) - _nextIndex) / pitch); target.ResampleCopyFrom(_data.ParentArray, _nextIndex + ( double )_data.MemOffset, targetLength, offsetInTarget, pitch); return(targetLength); } else if (iLastIndex < 0) { targetLength = -( int )((_nextIndex - 1d) / pitch) + 1; target.ResampleCopyFrom(_data.ParentArray, _nextIndex + ( double )_data.MemOffset, targetLength, offsetInTarget, pitch); return(targetLength); } else { target.ResampleCopyFrom(_data.ParentArray, _nextIndex + ( double )_data.MemOffset, targetLength, offsetInTarget, pitch); _nextIndex = dLastIndex + pitch; return(targetLength); } }
public override void PlaySample(int index, double dspTime) { if (_sampleBank.IsLoaded == false) { return; } PatternSample sampleInfo = _samples[index]; if (onPatternWillPlay != null) { onPatternWillPlay(sampleInfo, index, dspTime); } if (_envelopeModule != null) { if (sampleInfo.ProcessedSample == null) { sampleInfo.ProcessedSample = _sampleBank.GetProcessedSample(sampleInfo.SampleName, _envelopeModule.Envelope, sampleInfo.Pitch); } sampleInfo.ProcessedSample.PlayScheduled(_player, dspTime, _trackNb, sampleInfo.Gain); } else { GATData data = _sampleBank.GetAudioData(sampleInfo.SampleName); _player.PlayDataScheduled(data, dspTime, _trackNb, sampleInfo.Gain); } }
public int GetData(GATData target, int targetLength, int offsetInTarget, bool reverse = false) { int nextIndex = ( int )_nextIndex; int sign = reverse ? -1 : 1; int lastIndex = nextIndex + targetLength * sign; if (lastIndex >= _data.Count) { targetLength = _data.Count - nextIndex; } else if (lastIndex < 0) { targetLength = nextIndex + 1; lastIndex = 0; } if (reverse == false) { target.CopyFrom(_data.ParentArray, offsetInTarget, nextIndex + _data.MemOffset, targetLength); } else { target.CopyFrom(_data.ParentArray, offsetInTarget, lastIndex + _data.MemOffset, targetLength); target.Reverse(offsetInTarget, targetLength); } _nextIndex = ( int )lastIndex; return(targetLength); }
public override void RemoveSample(string name) { GATData data = _samplesByName[name]; base.RemoveSample(name); _cache.RemoveSample(data); }
/// <summary> /// Extracts the audio data from an AudioClip and sets it in a GATData object. /// Memory is allocated according to the specified GATDataAllocationMode. /// </summary> public static GATData ToGATData(this AudioClip clip, GATDataAllocationMode mode) { GATData data; float[] tempArray; tempArray = new float[clip.samples]; clip.GetData(tempArray, 0); #if UNITY_EDITOR if (Application.isPlaying == false) { mode = GATDataAllocationMode.Unmanaged; } #endif if (mode == GATDataAllocationMode.Managed) { data = GATManager.GetDataContainer(clip.samples); data.CopyFrom(tempArray, 0, 0, clip.samples); } else if (mode == GATDataAllocationMode.Fixed) { data = GATManager.GetFixedDataContainer(clip.samples, "ClipData: " + clip.name); data.CopyFrom(tempArray, 0, 0, clip.samples); } else { data = new GATData(tempArray); } return(data); }
public IGATProcessedSample GetProcessedSample(GATData sourceSample, double pitch, GATEnvelope envelope) { if (envelope == null) { envelope = GATEnvelope.nullEnvelope; } int i; List <ProcessedAudioChunk> chunks = _processedChunksInMemory[sourceSample]; ProcessedAudioChunk sample; for (i = 0; i < chunks.Count; i++) { if (chunks[i].envelope == envelope && chunks[i].Pitch == pitch) { sample = chunks[i]; return(sample); } } sample = new ProcessedAudioChunk(sourceSample, envelope, this, pitch); //Here is the main dif with base class chunks.Add(sample); return(sample); }
public void CleanUp() { if (_audioData != null) { _audioData.Release(); _audioData = null; } }
public override void AddSample( GATData data, string sampleName ) { base.AddSample( data, sampleName ); if( _cache == null ) _cache = new GATProcessedSamplesCache( _totalCapacity ); _cache.AddSample( data ); }
public void Init(GATData isample, GATTrack track, OnShouldMixSample callback, float gain = 1f) { AudioData = isample; _track = track; _onShouldMixSample = callback; _gain = gain; IsFirstChunk = true; _count = isample.Count; _fadeStart = -1; }
public void Init(GATData isample, AGATPanInfo panInfo, OnShouldMixSample callback, float gain = 1f) { AudioData = isample; PanInfo = panInfo; _onShouldMixSample = callback; _gain = gain; IsFirstChunk = true; _count = isample.Count; _fadeStart = -1; }
/// <summary> /// Initializes a new instance of the <see cref="GATAudioThreadStreamToCache"/> class. /// </summary> /// <param name="stream">The observed multichannel or mono stream.</param> /// <param name="caches">The caches to record to, one per channel must be provided.</param> /// <param name="handler">Optional callback fired when the cache is full.</param> public GATAudioThreadStreamToCache( IGATAudioThreadStream stream, GATData[] caches, AtEndHandler handler = null ) { _numFramesPerRead = stream.BufferSizePerChannel; Caches = caches; _stream = stream; _onEnd = handler; }
void OnAudioFilterRead(float[] data, int nbOfChannels) { if (__didInitialize == false) { __bufferHandle = GCHandle.Alloc(data, GCHandleType.Pinned); __bufferPointer = __bufferHandle.AddrOfPinnedObject(); AudioBuffer = new GATData(data); __didInitialize = true; } }
public override void AddSample(GATData data, string sampleName) { base.AddSample(data, sampleName); if (_cache == null) { _cache = new GATProcessedSamplesCache(_totalCapacity); } _cache.AddSample(data); }
public void RemoveSample( GATData sample ) { List< ProcessedAudioChunk > chunks = _processedChunksInMemory[ sample ]; int i; for( i = 0; i < chunks.Count; i++ ) { chunks[ i ].CleanUp(); } _processedChunksInMemory.Remove( sample ); }
public void RemoveSample(GATData sample) { List <ProcessedAudioChunk> chunks = _processedChunksInMemory[sample]; int i; for (i = 0; i < chunks.Count; i++) { chunks[i].CleanUp(); } _processedChunksInMemory.Remove(sample); }
/// <summary> /// Adds a sample to the bank, which will retain it, and manage cache for it /// if GATActiveSamplebank. /// </summary> public virtual void AddSample(GATData data, string sampleName) { if (_allSamples == null) { InitCollections(); } _samplesByName.Add(sampleName, data); _allSamples.Add(data); data.Retain(); _allKeys = null; }
protected void Dispose(bool explicitely) { if (_disposed) { return; } _sourceStream.RemoveAudioThreadStreamClient(this); _sourceStream = null; _sharedBuffer.Release(); _sharedBuffer = null; _disposed = true; }
/// <summary> /// Plays the sample directly. /// Panning may be controlled through the provided /// AGATPanInfo instance. /// </summary> public IGATBufferedSampleOptions PlayData(GATData sample, AGATPanInfo panInfo, float gain = 1f, OnShouldMixSample mixCallback = null) { sample.Retain(); BufferedSample newSample = GetBufferedSample(); newSample.Init(sample, panInfo, mixCallback, gain); lock ( _samplesToEnqueue ) { _samplesToEnqueue.Enqueue(newSample); } return(newSample); }
/// <summary> /// Additive copy to another GATData instance /// </summary> public void MixTo(GATData destination, int destinationIndex, int sourceIndex, int length) { float[] destinationArray = destination._parentArray; sourceIndex += _offset; length += sourceIndex; destinationIndex += destination._offset; while (sourceIndex < length) { destinationArray[destinationIndex] += _parentArray[sourceIndex]; destinationIndex++; sourceIndex++; } }
public void SetData(GATData data) { _nextIndex = 0d; if (_data != null) { _data.Release(); } _data = data; if (data != null) { data.Retain(); } }
/// <summary> /// Releases a specific sample and it's associated cache. /// </summary> public virtual void RemoveSample(string sampleName) { GATData data = _samplesByName[sampleName]; data.Release(); _samplesByName.Remove(sampleName); _allSamples.Remove(data); _allKeys = null; if (_allSamples.Count == 0) { _allSamples = null; _samplesByName = null; } }
public static void CleanUpStatics() { if (__didInitialize == false) { return; } __bufferHandle.Free(); __bufferPointer = IntPtr.Zero; __didInitialize = false; __wasAdded = false; AudioBuffer = null; }
/// <summary> /// The splitter will begin broadcasting it's /// sub streams immediately. /// </summary> public GATAudioThreadStreamSplitter(IGATAudioThreadStream stream, GATDataAllocationMode bufferAllocationMode) { int i; _sourceStreamChannels = stream.NbOfChannels; if (_sourceStreamChannels < 2) { Debug.LogWarning("source stream is mono: " + stream.StreamName); } IntPtr outputBufferPointer = IntPtr.Zero; _sharedBufferSize = stream.BufferSizePerChannel; if (bufferAllocationMode == GATDataAllocationMode.Unmanaged) { _sharedBufferArray = new float[_sharedBufferSize]; _sharedBuffer = new GATData(_sharedBufferArray); } else { if (bufferAllocationMode == GATDataAllocationMode.Fixed) { _sharedBuffer = GATManager.GetFixedDataContainer(_sharedBufferSize, "StreamSplitter buffer"); } else { _sharedBuffer = GATManager.GetDataContainer(_sharedBufferSize); } _sharedBufferArray = _sharedBuffer.ParentArray; outputBufferPointer = _sharedBuffer.GetPointer(); } _memOffset = _sharedBuffer.MemOffset; _streamProxies = new GATAudioThreadStreamProxy[_sourceStreamChannels]; for (i = 0; i < _sourceStreamChannels; i++) { _streamProxies[i] = new GATAudioThreadStreamProxy(_sharedBufferSize, 1, outputBufferPointer, _sharedBuffer.MemOffset, (stream.StreamName + " split " + i)); } stream.AddAudioThreadStreamClient(this); _sourceStream = stream; }
/// <summary> /// Additive copy and gain to another GATData instance /// </summary> public void GainMixTo(GATData destinationData, int sourceIndex, int destinationIndex, int length, float gain) { sourceIndex += _offset; length += sourceIndex; float[] destinationArray = destinationData.ParentArray; destinationIndex += destinationData._offset; while (sourceIndex < length) { destinationArray[destinationIndex] += _parentArray[sourceIndex] * gain; sourceIndex++; destinationIndex++; } }
/// <summary> /// The splitter will begin broadcasting it's /// sub streams immediately. /// </summary> public GATAudioThreadStreamSplitter( IGATAudioThreadStream stream, GATDataAllocationMode bufferAllocationMode ) { int i; _sourceStreamChannels = stream.NbOfChannels; if( _sourceStreamChannels < 2 ) { Debug.LogWarning( "source stream is mono: " + stream.StreamName ); } IntPtr outputBufferPointer = IntPtr.Zero; _sharedBufferSize = stream.BufferSizePerChannel; if( bufferAllocationMode == GATDataAllocationMode.Unmanaged ) { _sharedBufferArray = new float[ _sharedBufferSize ]; _sharedBuffer = new GATData( _sharedBufferArray ); } else { if( bufferAllocationMode == GATDataAllocationMode.Fixed ) { _sharedBuffer = GATManager.GetFixedDataContainer( _sharedBufferSize, "StreamSplitter buffer" ); } else { _sharedBuffer = GATManager.GetDataContainer( _sharedBufferSize ); } _sharedBufferArray = _sharedBuffer.ParentArray; outputBufferPointer = _sharedBuffer.GetPointer(); } _memOffset = _sharedBuffer.MemOffset; _streamProxies = new GATAudioThreadStreamProxy[ _sourceStreamChannels ]; for( i = 0; i < _sourceStreamChannels; i++ ) { _streamProxies[ i ] = new GATAudioThreadStreamProxy( _sharedBufferSize, 1, outputBufferPointer, _sharedBuffer.MemOffset, ( stream.StreamName + " split " + i ) ); } stream.AddAudioThreadStreamClient( this ); _sourceStream = stream; }
/// <summary> /// Allocates caches retrievable in the Caches property. /// </summary> public void AllocateCaches(double duration, bool managedData) { if (!_isInited) { Start(); } if (_streamToCache != null && Caches != null) { _streamToCache.ReleaseCache(); } cacheDuration = duration; _cacheNumFrames = ( int )(cacheDuration * GATInfo.OutputSampleRate); useManagedData = managedData; GATData[] caches = new GATData[_stream.NbOfChannels]; int i; for (i = 0; i < caches.Length; i++) { if (useManagedData) { if (_cacheNumFrames > GATManager.DefaultDataAllocator.LargestFreeChunkSize) { int j; for (j = 0; j < i; j++) { caches[i].Release(); } throw new GATException("Chunk is too large to be allocated in managed memory, consider using unmanaged setting"); } caches[i] = GATManager.GetDataContainer(_cacheNumFrames); } else { caches[i] = new GATData(new float[_cacheNumFrames]); } } _streamToCache.Loop = _loopedCaching; _streamToCache.Caches = caches; }
public ProcessedAudioChunk(GATData sourcesample, GATEnvelope ienvelope, GATProcessedSamplesCache parentCache, double pitch = 1d) { sourceSample = sourcesample; envelope = ienvelope; _parentCache = parentCache; if (envelope == GATEnvelope.nullEnvelope) //_cachedLength will never change { _cachedLength = sourcesample.Count; } else { _cachedLength = envelope.Length; } SetPitch(pitch); }
public int DoFade(GATData target, double dspTime, int lengthInSamples) { int offset = 0; double chunkDuration; float lerpVal; float fromGain, toGain; if (_startDspTime == 0d) { _startDspTime = dspTime; _fadeEndDspTime = dspTime + _duration; } else if (dspTime < _startDspTime) // fade out start, don't adjust length in samples: we will return it to signal fade hasn't finished { offset = ( int )((dspTime - _startDspTime) * GATInfo.OutputSampleRate); } chunkDuration = (( double )lengthInSamples - offset) / GATInfo.OutputSampleRate; if (chunkDuration + dspTime > _fadeEndDspTime) { chunkDuration = _fadeEndDspTime - dspTime; if (chunkDuration <= 0d) { return(0); } lengthInSamples = ( int )(chunkDuration * GATInfo.OutputSampleRate); } lerpVal = ( float )((dspTime - _startDspTime) / _duration); fromGain = Mathf.Lerp(_fromGain, _toGain, lerpVal); dspTime += chunkDuration; lerpVal = ( float )((dspTime - _startDspTime) / _duration); toGain = Mathf.Lerp(_fromGain, _toGain, lerpVal); target.Fade(fromGain, toGain, lengthInSamples - offset, offset); _lastGain = toGain; return(lengthInSamples); }
bool IGATTrackContributor.MixToTrack(GATData trackMonoBuffer, int trackNb) { if (_streamBuffer == null || _streamDataEmpty) { return(false); } if (_exclusive) { trackMonoBuffer.CopyFrom(_streamBuffer, 0, _streamOffset, GATInfo.AudioBufferSizePerChannel); } else { trackMonoBuffer.MixFrom(_streamBuffer, 0, _streamOffset, GATInfo.AudioBufferSizePerChannel); } return(true); }
/// <summary> /// Performs the same operation as ToGATData, but splits interleaved channels in seperate GATData /// instances. /// </summary> public static GATData[] ExtractChannels( this AudioClip clip, GATDataAllocationMode mode ) { GATData[] channelsData; float[] tempArray; int i; int length; tempArray = new float[ clip.samples * clip.channels ]; clip.GetData( tempArray, 0 ); channelsData = new GATData[ clip.channels ]; length = clip.samples; #if UNITY_EDITOR if( Application.isPlaying == false ) { mode = GATDataAllocationMode.Unmanaged; } #endif for( i = 0; i < clip.channels; i++ ) { if( mode == GATDataAllocationMode.Managed ) { channelsData[ i ] = GATManager.GetDataContainer( length ); } else if( mode == GATDataAllocationMode.Fixed ) { channelsData[ i ] = GATManager.GetFixedDataContainer( length, clip.name+" channel"+i+" data" ); } else { channelsData[ i ] = new GATData( new float[ length ] ); } channelsData[ i ].CopyFromInterlaced( tempArray, length, i, clip.channels ); } return channelsData; }
protected virtual void OnEnable() { if (GATInfo.NbOfChannels == 0) { return; } if (_player != null) //Object has just been deserialized, only setup transient objects { _panInfo = new GATDynamicPanInfo(_player, true); _panInfo.SetGains(_gains); _trackBuffer = GATManager.GetFixedDataContainer(GATInfo.AudioBufferSizePerChannel, "track" + TrackNb + " buffer"); _audioThreadStreamProxy = new GATAudioThreadStreamProxy(GATInfo.AudioBufferSizePerChannel, 1, _trackBuffer.GetPointer(), _trackBuffer.MemOffset, ("Track " + _trackNb + " stream")); _player.onPlayerWillMix += PlayerWillBeginMixing; _mute = _nextMute; //only _nextMute is serialized _active = true; } }
/// <summary> /// Performs the same operation as ToGATData, but splits interleaved channels in seperate GATData /// instances. /// </summary> public static GATData[] ExtractChannels(this AudioClip clip, GATDataAllocationMode mode) { GATData[] channelsData; float[] tempArray; int i; int length; tempArray = new float[clip.samples * clip.channels]; clip.GetData(tempArray, 0); channelsData = new GATData[clip.channels]; length = clip.samples; #if UNITY_EDITOR if (Application.isPlaying == false) { mode = GATDataAllocationMode.Unmanaged; } #endif for (i = 0; i < clip.channels; i++) { if (mode == GATDataAllocationMode.Managed) { channelsData[i] = GATManager.GetDataContainer(length); } else if (mode == GATDataAllocationMode.Fixed) { channelsData[i] = GATManager.GetFixedDataContainer(length, clip.name + " channel" + i + " data"); } else { channelsData[i] = new GATData(new float[length]); } channelsData[i].CopyFromInterlaced(tempArray, length, i, clip.channels); } return(channelsData); }
/// <summary> /// Called by GATPlayer. /// Needed when overriding default mixing: /// If a sample is routed through a track, /// it should be mixed to it. /// </summary> public void MixFrom(GATData data, int index, int offsetInBuffer, int length, float gain = 1f) { if (!_active) { return; } if (_bufferIsDirty) //Contains old data { int lastIndex = offsetInBuffer + length; if (lastIndex < GATInfo.AudioBufferSizePerChannel || offsetInBuffer > 0) //if what we want to add to the buffer doesn't fill it, let's clear it first { _trackBuffer.Clear(); } if (gain == 1f) { data.CopyTo(_trackBuffer, offsetInBuffer, index, length); // no need to mix on dirty or empty data, simply copy } else { data.CopyGainTo(_trackBuffer, index, offsetInBuffer, length, gain); } _bufferIsDirty = false; } else { if (gain == 1f) { data.MixTo(_trackBuffer, offsetInBuffer, index, length); } else { data.GainMixTo(_trackBuffer, index, offsetInBuffer, length, gain); } } NbOfMixedSamples++; _hasData = true; }
protected void FillWithResampledData(GATData sourceData, GATData targetData, int fromIndex, int targetLength, double pitch) { //check that we have enough samples to fulfill the request: int appliedLength = GATMaths.ClampedResampledLength(sourceData.Count - fromIndex, targetLength, pitch); if (appliedLength < 0) { #if GAT_DEBUG Debug.LogWarning("requested offset is out of bounds."); #endif return; } sourceData.ResampleCopyTo(fromIndex, targetData, appliedLength, pitch); //if we did not have enough samples, clear the rest: if (appliedLength < targetLength) { targetData.Clear(appliedLength, targetData.Count - appliedLength); } }
/// <summary> /// Additive copy and interpolated gain to another GATData instance /// </summary> public void MixSmoothedGainTo(int sourceIndex, GATData destination, int destinationIndex, int length, float fromGain, float toGain) { float interpolationDelta; float[] destinationArray; interpolationDelta = (toGain - fromGain) / length; destinationIndex += destination._offset; sourceIndex += _offset; length += sourceIndex; destinationArray = destination._parentArray; while (sourceIndex < length) { destinationArray[destinationIndex] += _parentArray[sourceIndex] * fromGain; fromGain += interpolationDelta; destinationIndex++; sourceIndex++; } }
public IGATProcessedSample GetProcessedSample( GATData sourceSample, double pitch, GATEnvelope envelope ) { if( envelope == null ) envelope = GATEnvelope.nullEnvelope; int i; List<ProcessedAudioChunk> chunks = _processedChunksInMemory[ sourceSample ]; ProcessedAudioChunk sample; for( i = 0; i < chunks.Count; i++ ) { if( chunks[i].envelope == envelope && chunks[i].Pitch == pitch ) { sample = chunks[i]; return sample; } } sample = new ProcessedAudioChunk( sourceSample, envelope, this, pitch ); //Here is the main dif with base class chunks.Add( sample ); return sample; }
public void AddSample( GATData sample ) { _processedChunksInMemory.Add( sample, new List< ProcessedAudioChunk >() ); }
/// <summary> /// Additive copy and gain to another GATData instance /// </summary> public void GainMixTo( GATData destinationData, int sourceIndex, int destinationIndex, int length, float gain ) { sourceIndex += _offset; length += sourceIndex; float[] destinationArray = destinationData.ParentArray; destinationIndex += destinationData._offset; while( sourceIndex < length ) { destinationArray[ destinationIndex ] += _parentArray[ sourceIndex ] * gain; sourceIndex++; destinationIndex++; } }
public void GlissCopyFrom( GATData sourceData, int fromIndex, double fromPitch, double toPitch ) { fromIndex += sourceData.MemOffset; GlissCopyFrom( sourceData.ParentArray, fromIndex, this.Count, fromPitch, toPitch ); }
//no processing public override void ProcessSample( GATData sample ) { }
void OnAudioFilterRead( float[] data, int nbOfChannels ) { if( __didInitialize == false ) { __bufferHandle = GCHandle.Alloc( data, GCHandleType.Pinned ); __bufferPointer = __bufferHandle.AddrOfPinnedObject(); AudioBuffer = new GATData( data ); __didInitialize = true; } }
public GATData[] LoadNext( BackgroundWorker worker, float[] deInterleaveBuffer ) { GATData[] containers; int i; int channels; if( _paths.Count == 0 ) { Status = LoadOperationStatus.Done; return null; } AGATAudioFile file; try { file = AGATAudioFile.OpenAudioFileAtPath( _paths.Dequeue() ); } catch( System.Exception e ) { #if UNITY_EDITOR Debug.LogException( e ); #endif FailReason = LoadOperationFailReason.CannotOpenFile; Status = LoadOperationStatus.Failed; return null; } using( file ) { channels = file.Channels; CurrentFileName = file.FileName; if( !_forceMono && channels > 1 ) { containers = new GATData[ channels ]; } else { containers = new GATData[ 1 ]; } for( i = 0; i < containers.Length; i++ ) { if( _allocationMode == GATDataAllocationMode.Fixed ) //GZComment: allocation fail leaks { try{ containers[ i ] = GATManager.GetFixedDataContainer( file.NumFrames, file.FileName ); } catch( System.Exception ex ) { ReleaseContainers( containers ); Status = LoadOperationStatus.Failed; FailReason = LoadOperationFailReason.OutOfPreAllocatedMemory; #if UNITY_EDITOR Debug.LogException( ex ); #endif return null; } } else if( _allocationMode == GATDataAllocationMode.Managed ) //GZComment: allocation fail leaks { try { containers[ i ] = GATManager.GetDataContainer( file.NumFrames ); } catch( System.Exception ex ) { ReleaseContainers( containers ); Status = LoadOperationStatus.Failed; FailReason = LoadOperationFailReason.NoLargeEnoughChunkInAllocator; #if UNITY_EDITOR Debug.LogException( ex ); #endif return null; } } else { containers[ i ] = new GATData( new float[ file.NumFrames ] ); } } int framesPerRead; int framesRead; int totalFramesRead = 0; if( channels > 1 ) { framesPerRead = deInterleaveBuffer.Length / channels; while( true ) { if( worker.CancellationPending ) { ReleaseContainers( containers ); return null; } framesRead = file.ReadNextChunk( deInterleaveBuffer, 0, framesPerRead ); if( _forceMono ) // Only supported for stereo files { int numSamples = framesRead * channels; for( i = 0; i < numSamples; i+= channels ) { deInterleaveBuffer[ i ] += deInterleaveBuffer[ i + 1 ]; } containers[ 0 ].CopyFromInterlaced( deInterleaveBuffer, framesRead, totalFramesRead, 0, channels ); } else { for( i = 0; i < channels; i++ ) { containers[ i ].CopyFromInterlaced( deInterleaveBuffer, framesRead, totalFramesRead, i, channels ); } } totalFramesRead += framesRead; if( _reportsProgress ) worker.ReportProgress( 0, new ProgressInfo( ( float )totalFramesRead / file.NumFrames, file.FileName ) ); if( framesRead < framesPerRead ) break; } } else { int framesLeft; while( totalFramesRead < file.NumFrames ) { if( worker.CancellationPending ) { ReleaseContainers( containers ); return null; } framesLeft = file.NumFrames - totalFramesRead; framesPerRead = ( framesLeft < 16384 ? framesLeft : 16384 ); framesRead = file.ReadNextChunk( containers[ 0 ].ParentArray, containers[ 0 ].MemOffset + totalFramesRead, framesPerRead ); totalFramesRead += framesRead; if( _reportsProgress ) worker.ReportProgress( 0, new ProgressInfo( ( float )totalFramesRead / file.NumFrames, file.FileName ) ); } } } return containers; }
/// <summary> /// Performs a resampled /// copy to another GATData /// instance. /// The resampling algorithm /// performs naive linear interpolation. /// </summary> /// <returns> /// The next interpolated index. /// </returns> public double ResampleCopyTo( double trueInterpolatedIndex, GATData destinationSample, int targetLength, double resamplingFactor ) { return destinationSample.ResampleCopyFrom( _parentArray, trueInterpolatedIndex, targetLength, 0, resamplingFactor ); }
/// <summary> /// Additive copy and interpolated gain to another GATData instance /// </summary> public void MixSmoothedGainTo( int sourceIndex, GATData destination, int destinationIndex, int length, float fromGain, float toGain ) { float interpolationDelta; float[] destinationArray; interpolationDelta = ( toGain - fromGain ) / length; destinationIndex += destination._offset; sourceIndex += _offset; length += sourceIndex; destinationArray = destination._parentArray; while( sourceIndex < length ) { destinationArray[destinationIndex] += _parentArray[sourceIndex] * fromGain; fromGain += interpolationDelta; destinationIndex ++; sourceIndex++; } }
/// <summary> /// Called by GATPlayer. /// Needed when overriding default mixing: /// If a sample is routed through a track, /// it should be mixed to it. /// </summary> public void MixFrom( GATData data, int index, int offsetInBuffer, int length, float gain = 1f ) { if( !_active ) return; if( _bufferIsDirty ) //Contains old data { int lastIndex = offsetInBuffer + length; if( lastIndex < GATInfo.AudioBufferSizePerChannel || offsetInBuffer > 0 ) //if what we want to add to the buffer doesn't fill it, let's clear it first { _trackBuffer.Clear(); } if( gain == 1f ) { data.CopyTo( _trackBuffer, offsetInBuffer, index, length ); // no need to mix on dirty or empty data, simply copy } else { data.CopyGainTo( _trackBuffer, index, offsetInBuffer, length, gain ); } _bufferIsDirty = false; } else { if( gain == 1f ) { data.MixTo( _trackBuffer, offsetInBuffer, index, length ); } else { data.GainMixTo( _trackBuffer, index, offsetInBuffer, length, gain ); } } NbOfMixedSamples++; _hasData = true; }
public ProcessedAudioChunk( GATData sourcesample, GATEnvelope ienvelope, GATProcessedSamplesCache parentCache, double pitch = 1d ) { sourceSample = sourcesample; envelope = ienvelope; _parentCache = parentCache; if( envelope == GATEnvelope.nullEnvelope ) //_cachedLength will never change { _cachedLength = sourcesample.Count; } else { _cachedLength = envelope.Length; } SetPitch( pitch ); }
/// <summary> /// Copies data from a GATData instance to another. /// </summary> public void CopyTo( GATData destinationData, int destinationIndex, int sourceIndex, int length ) { System.Array.Copy( _parentArray, sourceIndex + _offset, destinationData._parentArray, destinationIndex + destinationData._offset, length ); }
protected virtual void OnEnable() { if( GATInfo.NbOfChannels == 0 ) return; if( _player != null ) //Object has just been deserialized, only setup transient objects { _panInfo = new GATDynamicPanInfo( _player, true ); _panInfo.SetGains( _gains ); _trackBuffer = GATManager.GetFixedDataContainer( GATInfo.AudioBufferSizePerChannel, "track"+TrackNb+" buffer" ); _audioThreadStreamProxy = new GATAudioThreadStreamProxy( GATInfo.AudioBufferSizePerChannel, 1, _trackBuffer.GetPointer(), _trackBuffer.MemOffset, ( "Track " + _trackNb + " stream" ) ); _player.onPlayerWillMix += PlayerWillBeginMixing; _mute = _nextMute; //only _nextMute is serialized _active = true; } }
/// <summary> /// Copies data from a GATData instance to another and /// applies interpolated gain. /// </summary> public void CopySmoothedGainTo( int sourceIndex, GATData destination, int destinationIndex, int length, float fromGain, float toGain ) { sourceIndex += _offset; destination.CopySmoothedGainFrom( _parentArray, sourceIndex, destinationIndex, length, fromGain, toGain ); }
/// <summary> /// Additive copy to another GATData instance /// </summary> public void MixTo( GATData destination, int destinationIndex, int sourceIndex, int length ) { float[] destinationArray = destination._parentArray; sourceIndex += _offset; length += sourceIndex; destinationIndex += destination._offset; while( sourceIndex < length ) { destinationArray[ destinationIndex ] += _parentArray[sourceIndex]; destinationIndex ++; sourceIndex++; } }
public void CleanUp() { if( _audioData != null ) { _audioData.Release(); _audioData = null; } }
/// <summary> /// Allocates caches retrievable in the Caches property. /// </summary> public void AllocateCaches( double duration, bool managedData ) { if( !_isInited ) Start (); if( _streamToCache != null && Caches != null ) { _streamToCache.ReleaseCache(); } cacheDuration = duration; _cacheNumFrames = ( int )( cacheDuration * GATInfo.OutputSampleRate ); useManagedData = managedData; GATData[] caches = new GATData[ _stream.NbOfChannels ]; int i; for( i = 0; i < caches.Length; i++ ) { if( useManagedData ) { if( _cacheNumFrames > GATManager.DefaultDataAllocator.LargestFreeChunkSize ) { int j; for( j = 0; j < i; j++ ) { caches[ i ].Release(); } throw new GATException( "Chunk is too large to be allocated in managed memory, consider using unmanaged setting" ); } caches[ i ] = GATManager.GetDataContainer( _cacheNumFrames ); } else { caches[ i ] = new GATData( new float[ _cacheNumFrames ] ); } } _streamToCache.Loop = _loopedCaching; _streamToCache.Caches = caches; }
void UpdateContainer() { if( _audioData != null ) { _audioData.Release(); } #if UNITY_EDITOR if( Application.isPlaying ) { _audioData = GATManager.GetDataContainer( _cachedLength ); } else { _audioData = new GATData( new float[ _cachedLength ] ); } #else _audioData = GATManager.GetDataContainer( _cachedLength ); #endif _audioData.Retain(); }
protected void FillWithSampleData( GATData sourceData, GATData targetData, int fromIndex, int length ) { bool tooLong = ( fromIndex + length > sourceData.Count ); int appliedLength = tooLong ? sourceData.Count - fromIndex : length; if( appliedLength < 0 ) { #if GAT_DEBUG Debug.LogWarning( "requested offset is out of bounds." ); #endif return; } sourceData.CopyTo( targetData, 0, fromIndex, appliedLength ); #if GAT_DEBUG if( tooLong ) { Debug.LogWarning( "requested length at fromIndex out of bounds, filling as much as possible" ); } #endif }
protected void FillWithResampledData( GATData sourceData, GATData targetData, int fromIndex, int targetLength, double pitch ) { //check that we have enough samples to fulfill the request: int appliedLength = GATMaths.ClampedResampledLength( sourceData.Count - fromIndex, targetLength, pitch ); if( appliedLength < 0 ) { #if GAT_DEBUG Debug.LogWarning( "requested offset is out of bounds." ); #endif return; } sourceData.ResampleCopyTo( fromIndex, targetData, appliedLength, pitch ); //if we did not have enough samples, clear the rest: if( appliedLength < targetLength ) { targetData.Clear( appliedLength, targetData.Count - appliedLength ); } }
/// <summary> /// Immediately applies all /// processing properties to /// the passed GATData object. /// </summary> public virtual void ProcessSample( GATData sample ) { if( _normalize ) sample.Normalize( _normalizeValue ); if( _reverse ) sample.Reverse(); if( _fadeInSamples > 0 ) sample.FadeIn( _fadeInSamples ); if( _fadeOutSamples > 0 ) sample.FadeOut( _fadeOutSamples ); }
public ProgressInfo( GATData[] channelData, string filename ) { progress = 1f; data = channelData; fileName = filename; }
/// <summary> /// Performs a resampled /// copy to another /// GATData instance /// The resampling algorithm /// performs naive linear interpolation. /// Warning: for resampling in chunks, use /// the method of the same name which returns /// a double interpolated index. /// </summary> public void ResampleCopyTo( int sourceIndex, GATData destinationSample, int targetLength, double resamplingFactor ) { sourceIndex += _offset; destinationSample.ResampleCopyFrom( _parentArray, ( double )sourceIndex, targetLength, 0, resamplingFactor ); }
void ReleaseContainers( GATData[] containers ) { int i; if( containers != null ) { for( i = 0; i < containers.Length; i++ ) { if( containers[ i ] != null ) containers[ i ].Release(); } } }
bool IGATTrackContributor.MixToTrack( GATData trackMonoBuffer, int trackNb ) { if( _streamBuffer == null || _streamDataEmpty ) return false; if( _exclusive ) { trackMonoBuffer.CopyFrom( _streamBuffer, 0, _streamOffset, GATInfo.AudioBufferSizePerChannel ); } else { trackMonoBuffer.MixFrom( _streamBuffer, 0, _streamOffset, GATInfo.AudioBufferSizePerChannel ); } return true; }