internal void SetData(IntPtr data, AudioFormat fmt, uint hz, uint size) { AL10.alBufferData(_handle, (int)fmt, data, (int)size, (int)hz); ALUtils.CheckALError("unable to set audio buffer data"); AL10.alGetBufferi(_handle, AL10.AL_BITS, out int bits); AL10.alGetBufferi(_handle, AL10.AL_CHANNELS, out int channels); AL10.alGetBufferi(_handle, AL10.AL_SIZE, out int unpackedSize); Format = fmt; DataSize = (uint)unpackedSize; Duration = TimeSpan.FromSeconds((double)(unpackedSize / ((bits / 8) * channels)) / hz); }
public TimeSpan GetDuration() { int sizeInBytes; int channels; int bits; int lengthInSamples; AL10.alGetBufferi(_handle, AL10.AL_SIZE, out sizeInBytes); AL10.alGetBufferi(_handle, AL10.AL_CHANNELS, out channels); AL10.alGetBufferi(_handle, AL10.AL_BITS, out bits); lengthInSamples = sizeInBytes * 8 / (channels * bits); int frequency; AL10.alGetBufferi(_handle, AL10.AL_FREQUENCY, out frequency); return(TimeSpan.FromSeconds(lengthInSamples / (float)frequency)); }
public void GetBufferData( IALSource source, IALBuffer[] buffer, IntPtr samples, int samplesLen, AudioChannels channels ) { int copySize1 = samplesLen / (int)channels; int copySize2 = 0; // Where are we now? int offset; AL10.alGetSourcei( (source as OpenALSource).Handle, AL11.AL_SAMPLE_OFFSET, out offset ); // Is that longer than what the active buffer has left...? uint buf = (buffer[0] as OpenALBuffer).Handle; int len; AL10.alGetBufferi( buf, AL10.AL_SIZE, out len ); len /= 2; // FIXME: Assuming 16-bit! len /= (int)channels; if (offset > len) { copySize2 = copySize1; copySize1 = 0; offset -= len; } else if (offset + copySize1 > len) { copySize2 = copySize1 - (len - offset); copySize1 = (len - offset); } // Copy! if (copySize1 > 0) { ALEXT.alGetBufferSamplesSOFT( buf, offset, copySize1, channels == AudioChannels.Stereo ? ALEXT.AL_STEREO_SOFT : ALEXT.AL_MONO_SOFT, ALEXT.AL_FLOAT_SOFT, samples ); offset = 0; } if (buffer.Length > 1 && copySize2 > 0) { ALEXT.alGetBufferSamplesSOFT( (buffer[1] as OpenALBuffer).Handle, 0, copySize2, channels == AudioChannels.Stereo ? ALEXT.AL_STEREO_SOFT : ALEXT.AL_MONO_SOFT, ALEXT.AL_FLOAT_SOFT, samples + (copySize1 * (int)channels) ); } }
public IALBuffer ConvertStereoToMono(IALBuffer buffer) { OpenALBuffer buf = buffer as OpenALBuffer; int bufLen, bits; AL10.alGetBufferi( buf.Handle, AL10.AL_SIZE, out bufLen ); AL10.alGetBufferi( buf.Handle, AL10.AL_BITS, out bits ); bits /= 8; #if VERBOSE_AL_DEBUGGING CheckALError(); #endif byte[] data = new byte[bufLen]; GCHandle dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); IntPtr dataPtr = dataHandle.AddrOfPinnedObject(); ALEXT.alGetBufferSamplesSOFT( buf.Handle, 0, bufLen / bits / 2, ALEXT.AL_STEREO_SOFT, bits == 2 ? ALEXT.AL_SHORT_SOFT : ALEXT.AL_BYTE_SOFT, dataPtr ); #if VERBOSE_AL_DEBUGGING CheckALError(); #endif byte[] monoData = new byte[bufLen / 2]; GCHandle monoHandle = GCHandle.Alloc(monoData, GCHandleType.Pinned); IntPtr monoPtr = monoHandle.AddrOfPinnedObject(); unsafe { if (bits == 2) { short *src = (short *)dataPtr; short *dst = (short *)monoPtr; for (int i = 0; i < monoData.Length / 2; i += 1) { dst[i] = (short)(((int)src[0] + (int)src[1]) / 2); src += 2; } } else { sbyte *src = (sbyte *)dataPtr; sbyte *dst = (sbyte *)monoPtr; for (int i = 0; i < monoData.Length; i += 1) { dst[i] = (sbyte)(((short)src[0] + (short)src[1]) / 2); src += 2; } } } monoHandle.Free(); dataHandle.Free(); data = null; return(GenBuffer( monoData, (uint)buf.SampleRate, 1, 0, 0, false, (uint)bits - 1 )); }
public IALBuffer GenBuffer( byte[] data, uint sampleRate, uint channels, uint loopStart, uint loopEnd, bool isADPCM, uint formatParameter ) { uint result; // Generate the buffer now, in case we need to perform alBuffer ops. AL10.alGenBuffers(1, out result); #if VERBOSE_AL_DEBUGGING CheckALError(); #endif int format; int length = data.Length; if (isADPCM) { format = (channels == 2) ? ALEXT.AL_FORMAT_STEREO_MSADPCM_SOFT : ALEXT.AL_FORMAT_MONO_MSADPCM_SOFT; AL10.alBufferi( result, ALEXT.AL_UNPACK_BLOCK_ALIGNMENT_SOFT, (int)formatParameter ); } else { if (formatParameter == 1) { format = (channels == 2) ? AL10.AL_FORMAT_STEREO16: AL10.AL_FORMAT_MONO16; /* We have to perform extra data validation on * PCM16 data, as the MS SoundEffect builder will * leave extra bytes at the end which will confuse * alBufferData and throw an AL_INVALID_VALUE. * -flibit */ length &= 0x7FFFFFFE; } else { format = (channels == 2) ? AL10.AL_FORMAT_STEREO8: AL10.AL_FORMAT_MONO8; } } // Load it! AL10.alBufferData( result, format, data, length, (int)sampleRate ); #if VERBOSE_AL_DEBUGGING CheckALError(); #endif // Calculate the duration now, after we've unpacked the buffer int bufLen, bits; AL10.alGetBufferi( result, AL10.AL_SIZE, out bufLen ); AL10.alGetBufferi( result, AL10.AL_BITS, out bits ); if (bufLen == 0 || bits == 0) { throw new InvalidOperationException( "OpenAL buffer allocation failed!" ); } TimeSpan resultDur = TimeSpan.FromSeconds( bufLen / (bits / 8) / channels / ((double)sampleRate) ); // Set the loop points, if applicable if (loopStart > 0 || loopEnd > 0) { AL10.alBufferiv( result, ALEXT.AL_LOOP_POINTS_SOFT, new int[] { (int)loopStart, (int)loopEnd } ); } #if VERBOSE_AL_DEBUGGING CheckALError(); #endif // Finally. return(new OpenALBuffer(result, resultDur, (int)channels, (int)sampleRate)); }
private void INTERNAL_bufferData( byte[] data, uint sampleRate, uint channels, uint loopStart, uint loopEnd, bool isADPCM, uint formatParameter ) { if (OpenALDevice.Instance == null) { throw new NoAudioHardwareException(); } // Generate the buffer now, in case we need to perform alBuffer ops. AL10.alGenBuffers((IntPtr)1, out INTERNAL_buffer); int format; if (isADPCM) { format = (channels == 2) ? ALEXT.AL_FORMAT_STEREO_MSADPCM_SOFT : ALEXT.AL_FORMAT_MONO_MSADPCM_SOFT; AL10.alBufferi( INTERNAL_buffer, ALEXT.AL_UNPACK_BLOCK_ALIGNMENT_SOFT, (int)formatParameter ); } else { if (formatParameter == 1) { format = (channels == 2) ? AL10.AL_FORMAT_STEREO16: AL10.AL_FORMAT_MONO16; } else { format = (channels == 2) ? AL10.AL_FORMAT_STEREO8: AL10.AL_FORMAT_MONO8; } } // Load it! AL10.alBufferData( INTERNAL_buffer, format, data, (IntPtr)data.Length, (IntPtr)sampleRate ); // Calculate the duration now, after we've unpacked the buffer int bufLen, bits; AL10.alGetBufferi( INTERNAL_buffer, AL10.AL_SIZE, out bufLen ); AL10.alGetBufferi( INTERNAL_buffer, AL10.AL_BITS, out bits ); Duration = TimeSpan.FromSeconds( bufLen / (bits / 8) / channels / ((double)sampleRate) ); // Set the loop points, if applicable if (loopStart > 0 || loopEnd > 0) { AL10.alBufferiv( INTERNAL_buffer, ALEXT.AL_LOOP_POINTS_SOFT, new int[] { (int)loopStart, (int)loopEnd } ); } }
public unsafe IALBuffer ConvertStereoToMono(IALBuffer buffer) { OpenALBuffer buf = buffer as OpenALBuffer; int bufLen, bits; AL10.alGetBufferi( buf.Handle, AL10.AL_SIZE, out bufLen ); AL10.alGetBufferi( buf.Handle, AL10.AL_BITS, out bits ); bits /= 8; #if VERBOSE_AL_DEBUGGING CheckALError(); #endif byte[] data = new byte[bufLen]; byte[] monoData = new byte[bufLen / 2]; fixed(byte *dataPtr = &data[0]) fixed(byte *monoPtr = &monoData[0]) { ALEXT.alGetBufferSamplesSOFT( buf.Handle, 0, bufLen / bits / 2, ALEXT.AL_STEREO_SOFT, bits == 2 ? ALEXT.AL_SHORT_SOFT : ALEXT.AL_BYTE_SOFT, (IntPtr)dataPtr ); #if VERBOSE_AL_DEBUGGING CheckALError(); #endif if (bits == 2) { short *src = (short *)dataPtr; short *dst = (short *)monoPtr; for (int i = 0; i < monoData.Length / 2; i += 1) { dst[i] = (short)(((int)src[0] + (int)src[1]) / 2); src += 2; } } else { sbyte *src = (sbyte *)dataPtr; sbyte *dst = (sbyte *)monoPtr; for (int i = 0; i < monoData.Length; i += 1) { dst[i] = (sbyte)(((short)src[0] + (short)src[1]) / 2); src += 2; } } } return(GenBuffer( monoData, (uint)buf.SampleRate, 1, 0, 0, false, (uint)bits - 1 )); }
public IALBuffer GenBuffer( byte[] data, uint sampleRate, uint channels, uint loopStart, uint loopEnd, bool isADPCM, uint formatParameter ) { uint result; // Generate the buffer now, in case we need to perform alBuffer ops. AL10.alGenBuffers((IntPtr)1, out result); int format; if (isADPCM) { format = (channels == 2) ? ALEXT.AL_FORMAT_STEREO_MSADPCM_SOFT : ALEXT.AL_FORMAT_MONO_MSADPCM_SOFT; AL10.alBufferi( result, ALEXT.AL_UNPACK_BLOCK_ALIGNMENT_SOFT, (int)formatParameter ); } else { if (formatParameter == 1) { format = (channels == 2) ? AL10.AL_FORMAT_STEREO16: AL10.AL_FORMAT_MONO16; } else { format = (channels == 2) ? AL10.AL_FORMAT_STEREO8: AL10.AL_FORMAT_MONO8; } } // Load it! AL10.alBufferData( result, format, data, (IntPtr)data.Length, (IntPtr)sampleRate ); // Calculate the duration now, after we've unpacked the buffer int bufLen, bits; AL10.alGetBufferi( result, AL10.AL_SIZE, out bufLen ); AL10.alGetBufferi( result, AL10.AL_BITS, out bits ); TimeSpan resultDur = TimeSpan.FromSeconds( bufLen / (bits / 8) / channels / ((double)sampleRate) ); // Set the loop points, if applicable if (loopStart > 0 || loopEnd > 0) { AL10.alBufferiv( result, ALEXT.AL_LOOP_POINTS_SOFT, new int[] { (int)loopStart, (int)loopEnd } ); } // Finally. return(new OpenALBuffer(result, resultDur)); }
private void INTERNAL_bufferData( byte[] data, uint sampleRate, uint channels, uint loopStart, uint loopEnd, bool isADPCM, uint formatParameter ) { if (OpenALDevice.Instance == null) { throw new NoAudioHardwareException(); } // Generate the buffer now, in case we need to perform alBuffer ops. AL10.alGenBuffers((IntPtr)1, out INTERNAL_buffer); int format; if (isADPCM) { Platform.AssertSupported("ADPCM"); format = (channels == 2) ? ALEXT.AL_FORMAT_STEREO_MSADPCM_SOFT : ALEXT.AL_FORMAT_MONO_MSADPCM_SOFT; AL10.alBufferi( INTERNAL_buffer, ALEXT.AL_UNPACK_BLOCK_ALIGNMENT_SOFT, (int)formatParameter ); } else { if (formatParameter == 1) { format = (channels == 2) ? AL10.AL_FORMAT_STEREO16: AL10.AL_FORMAT_MONO16; } else { format = (channels == 2) ? AL10.AL_FORMAT_STEREO8: AL10.AL_FORMAT_MONO8; } } // Load it! AL10.alBufferData( INTERNAL_buffer, format, data, (IntPtr)data.Length, (IntPtr)sampleRate ); // Calculate the duration now, after we've unpacked the buffer int bufLen, bits; AL10.alGetBufferi( INTERNAL_buffer, AL10.AL_SIZE, out bufLen ); AL10.alGetBufferi( INTERNAL_buffer, AL10.AL_BITS, out bits ); Duration = TimeSpan.FromSeconds( bufLen / (bits / 8) / channels / ((double)sampleRate) ); // Compute the default loop end point (end of the buffer), because // some content builders automatically set a loop endpoint here instead of at 0 int defaultEndPoint = (bufLen / (bits / 8)) / (int)channels; var hasCustomStartPoint = (loopStart > 0); var hasCustomEndPoint = ( (loopEnd > loopStart) && (loopEnd < defaultEndPoint) ); if (hasCustomStartPoint || hasCustomEndPoint) { // Set the loop points, if applicable Platform.AssertSupported("CustomLoopPoints"); AL10.alBufferiv( INTERNAL_buffer, ALEXT.AL_LOOP_POINTS_SOFT, new int[] { (int)loopStart, (int)loopEnd } ); } }