public AudioEngine( string settingsFile, TimeSpan lookAheadTime, string rendererId ) { if (String.IsNullOrEmpty(settingsFile)) { throw new ArgumentNullException("settingsFile"); } // Read entire file into memory, pin buffer buffer = TitleContainer.ReadAllBytes(settingsFile); pin = GCHandle.Alloc(buffer, GCHandleType.Pinned); // Generate engine parameters FAudio.FACTRuntimeParameters settings = new FAudio.FACTRuntimeParameters(); settings.pGlobalSettingsBuffer = pin.AddrOfPinnedObject(); settings.globalSettingsBufferSize = (uint)buffer.Length; xactNotificationFunc = OnXACTNotification; settings.fnNotificationCallback = Marshal.GetFunctionPointerForDelegate( xactNotificationFunc ); // Special parameters from constructor settings.lookAheadTime = (uint)lookAheadTime.Milliseconds; if (!string.IsNullOrEmpty(rendererId)) { // FIXME: wchar_t? -flibit settings.pRendererID = Marshal.StringToHGlobalAuto(rendererId); } // Init engine, finally FAudio.FACTCreateEngine(0, out handle); if (FAudio.FACTAudioEngine_Initialize(handle, ref settings) != 0) { throw new InvalidOperationException( "Engine initialization failed!" ); } // Free the settings strings if (settings.pRendererID != IntPtr.Zero) { Marshal.FreeHGlobal(settings.pRendererID); } // Grab RendererDetails ushort rendererCount; FAudio.FACTAudioEngine_GetRendererCount( handle, out rendererCount ); if (rendererCount == 0) { Dispose(); throw new NoAudioHardwareException(); } rendererDetails = new RendererDetail[rendererCount]; char[] displayName = new char[0xFF]; char[] rendererID = new char[0xFF]; for (ushort i = 0; i < rendererCount; i += 1) { FAudio.FACTRendererDetails details; FAudio.FACTAudioEngine_GetRendererDetails( handle, i, out details ); unsafe { for (int j = 0; j < 0xFF; j += 1) { displayName[j] = (char)details.displayName[j]; rendererID[j] = (char)details.rendererID[j]; } } rendererDetails[i] = new RendererDetail( new string(displayName), new string(rendererID) ); } // Init 3D audio handle3D = new byte[FAudio.F3DAUDIO_HANDLE_BYTESIZE]; FAudio.FACT3DInitialize( handle, handle3D ); // Grab channel count for DSP_SETTINGS FAudio.FAudioWaveFormatExtensible mixFormat; FAudio.FACTAudioEngine_GetFinalMixFormat( handle, out mixFormat ); channels = mixFormat.Format.nChannels; // All XACT references have to go through here... notificationDesc = new FAudio.FACTNotificationDescription(); }
public AudioEngine( string settingsFile, TimeSpan lookAheadTime, string rendererId ) { if (String.IsNullOrEmpty(settingsFile)) { throw new ArgumentNullException("settingsFile"); } // Allocate (but don't initialize just yet!) FAudio.FACTCreateEngine(0, out handle); // Grab RendererDetails ushort rendererCount; FAudio.FACTAudioEngine_GetRendererCount( handle, out rendererCount ); if (rendererCount == 0) { FAudio.FACTAudioEngine_Release(handle); throw new NoAudioHardwareException(); } rendererDetails = new RendererDetail[rendererCount]; byte[] converted = new byte[0xFF * sizeof(short)]; for (ushort i = 0; i < rendererCount; i += 1) { FAudio.FACTRendererDetails details; FAudio.FACTAudioEngine_GetRendererDetails( handle, i, out details ); unsafe { Marshal.Copy((IntPtr)details.displayName, converted, 0, converted.Length); string name = System.Text.Encoding.Unicode.GetString(converted).TrimEnd('\0'); Marshal.Copy((IntPtr)details.rendererID, converted, 0, converted.Length); string id = System.Text.Encoding.Unicode.GetString(converted).TrimEnd('\0'); rendererDetails[i] = new RendererDetail(name, id); } } // Read entire file into memory, let FACT manage the pointer IntPtr bufferLen; IntPtr buffer = TitleContainer.ReadToPointer(settingsFile, out bufferLen); // Generate engine parameters FAudio.FACTRuntimeParameters settings = new FAudio.FACTRuntimeParameters(); settings.pGlobalSettingsBuffer = buffer; settings.globalSettingsBufferSize = (uint)bufferLen; settings.globalSettingsFlags = FAudio.FACT_FLAG_MANAGEDATA; xactNotificationFunc = OnXACTNotification; settings.fnNotificationCallback = Marshal.GetFunctionPointerForDelegate( xactNotificationFunc ); // Special parameters from constructor settings.lookAheadTime = (uint)lookAheadTime.Milliseconds; if (!string.IsNullOrEmpty(rendererId)) { // FIXME: wchar_t? -flibit settings.pRendererID = Marshal.StringToHGlobalAuto(rendererId); } // Init engine, finally if (FAudio.FACTAudioEngine_Initialize(handle, ref settings) != 0) { throw new InvalidOperationException( "Engine initialization failed!" ); } // Free the settings strings if (settings.pRendererID != IntPtr.Zero) { Marshal.FreeHGlobal(settings.pRendererID); } // Init 3D audio handle3D = new byte[FAudio.F3DAUDIO_HANDLE_BYTESIZE]; FAudio.FACT3DInitialize( handle, handle3D ); // Grab channel count for DSP_SETTINGS FAudio.FAudioWaveFormatExtensible mixFormat; FAudio.FACTAudioEngine_GetFinalMixFormat( handle, out mixFormat ); channels = mixFormat.Format.nChannels; // All XACT references have to go through here... notificationDesc = new FAudio.FACTNotificationDescription(); notificationDesc.flags = FAudio.FACT_FLAG_NOTIFICATION_PERSIST; notificationDesc.type = FAudio.FACTNOTIFICATIONTYPE_WAVEBANKDESTROYED; FAudio.FACTAudioEngine_RegisterNotification( handle, ref notificationDesc ); notificationDesc.type = FAudio.FACTNOTIFICATIONTYPE_SOUNDBANKDESTROYED; FAudio.FACTAudioEngine_RegisterNotification( handle, ref notificationDesc ); notificationDesc.type = FAudio.FACTNOTIFICATIONTYPE_CUEDESTROYED; FAudio.FACTAudioEngine_RegisterNotification( handle, ref notificationDesc ); }