Skip to content

Commit

Permalink
[AudioToolbox] Implement Xcode 16.0 beta 1-6 changes. (#20856)
Browse files Browse the repository at this point in the history
Note: there were no changes in beta 2, beta 3, beta 4, beta 5 or beta 6.
  • Loading branch information
rolfbjarne authored Aug 27, 2024
1 parent 54fd609 commit 84bcea0
Show file tree
Hide file tree
Showing 17 changed files with 516 additions and 80 deletions.
126 changes: 126 additions & 0 deletions src/AudioToolbox/AudioConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,20 @@ public enum AudioConverterPrimeMethod // typedef UInt32 AudioConverterPropertyID
None = 2
}

[Flags]
#if NET
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
#else
[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
#endif
public enum AudioConverterOptions : uint {
None = 0,
Unbuffered = 1 << 16,
}

#if NET
[SupportedOSPlatform ("ios")]
[SupportedOSPlatform ("maccatalyst")]
Expand Down Expand Up @@ -441,6 +455,49 @@ public bool CanResumeFromInterruption {
return new AudioConverter (ptr, true);
}

/// <summary>Create a new AudioConverter with the specified options.</summary>
/// <param name="sourceFormat">The format of the source audio to be converted.</param>
/// <param name="destinationFormat">The format to convert the source audio to.</param>
/// <param name="options">Any <see cref="AudioConverterOptions" /> to use.</param>
/// <param name="error">In case of failure, will contain the error code for the failure. Otherwise the value <see cref="AudioConverterError.None" /> will be returned.</param>
/// <returns>A new AudioConverter instance, or null in case of failure.</returns>
#if NET
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
#else
[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
#endif
public static AudioConverter? Create (AudioStreamBasicDescription sourceFormat, AudioStreamBasicDescription destinationFormat, AudioConverterOptions options, out AudioConverterError error)
{
IntPtr ptr = default (IntPtr);
unsafe {
error = AudioConverterNewWithOptions (&sourceFormat, &destinationFormat, options, &ptr);
}
if (error != AudioConverterError.None)
return null;
return new AudioConverter (ptr, true);
}

/// <summary>Create a new AudioConverter with the specified options.</summary>
/// <param name="sourceFormat">The format of the source audio to be converted.</param>
/// <param name="destinationFormat">The format to convert the source audio to.</param>
/// <param name="options">Any <see cref="AudioConverterOptions" /> to use.</param>
/// <returns>A new AudioConverter instance, or null in case of failure.</returns>
#if NET
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
#else
[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
#endif
public static AudioConverter? Create (AudioStreamBasicDescription sourceFormat, AudioStreamBasicDescription destinationFormat, AudioConverterOptions options)
{
return Create (sourceFormat, destinationFormat, options, out var _);
}

public static AudioFormatType []? DecodeFormats {
get {
return GetFormats (AudioFormatProperty.DecodeFormatIDs);
Expand Down Expand Up @@ -641,6 +698,49 @@ static AudioConverterError FillComplexBufferShared (IntPtr inAudioConverter, ref
}
}

#if NET
public delegate void PrepareCompletionCallback (AudioConverterError status);

[UnmanagedCallersOnly]
static void PrepareCompletionHandler (IntPtr block, int status)
{
var del = BlockLiteral.GetTarget<PrepareCompletionCallback> (block);
if (del is not null)
del ((AudioConverterError) status);
}

/// <summary>Optimizes any subsequent creation of audio converters in this process.</summary>
/// <param name="flags">Reserved; always pass 0.</param>
/// <param name="ioReserved">Reserved; always pass IntPtr.Zero.</param>
/// <param name="completionCallback">Optional callback to invoke when the preparation is complete.</param>
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
[BindingImpl (BindingImplOptions.Optimizable)]
public unsafe static void Prepare (uint flags = 0, IntPtr ioReserved = default (IntPtr), PrepareCompletionCallback? completionCallback = null)
{
if (completionCallback is null) {
AudioConverterPrepare (flags, ioReserved, null);
} else {
delegate* unmanaged<IntPtr, int, void> trampoline = &PrepareCompletionHandler;
using var block = new BlockLiteral (trampoline, completionCallback, typeof (AudioConverter), nameof (PrepareCompletionHandler));
AudioConverterPrepare (flags, ioReserved, &block);
}
}

/// <summary>Optimizes any subsequent creation of audio converters in this process.</summary>
/// <param name="completionCallback">Callback to invoke when the preparation is complete.</param>
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
public unsafe static void Prepare (PrepareCompletionCallback completionCallback)
{
Prepare (0, IntPtr.Zero, completionCallback);
}
#endif // NET

public AudioConverterError Reset ()
{
return AudioConverterReset (Handle);
Expand Down Expand Up @@ -743,6 +843,32 @@ void SetProperty (AudioConverterPropertyID propertyID, double value)
unsafe static extern AudioConverterError AudioConverterNewSpecific (AudioStreamBasicDescription* inSourceFormat, AudioStreamBasicDescription* inDestinationFormat,
int inNumberClassDescriptions, AudioClassDescription* inClassDescriptions, IntPtr* outAudioConverter);

#if NET
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
#else
[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
#endif
[DllImport (Constants.AudioToolboxLibrary)]
unsafe static extern void AudioConverterPrepare (uint inFlags, IntPtr ioReserved, BlockLiteral* block);

#if NET
[SupportedOSPlatform ("ios18.0")]
[SupportedOSPlatform ("maccatalyst18.0")]
[SupportedOSPlatform ("macos15.0")]
[SupportedOSPlatform ("tvos18.0")]
#else
[Watch (11, 0), TV (18, 0), Mac (15, 0), iOS (18, 0), MacCatalyst (18, 0)]
#endif
[DllImport (Constants.AudioToolboxLibrary)]
unsafe static extern /* OSStatus */ AudioConverterError AudioConverterNewWithOptions (
/* const AudioStreamBasicDescription * */ AudioStreamBasicDescription* inSourceFormat,
/* const AudioStreamBasicDescription * */ AudioStreamBasicDescription* inDestinationFormat,
/* AudioConverterOptions */ AudioConverterOptions inOptions,
/* AudioConverterRef __nullable * __nonnull */ IntPtr* outAudioConverter);

[DllImport (Constants.AudioToolboxLibrary)]
static extern AudioConverterError AudioConverterDispose (IntPtr inAudioConverter);

Expand Down
195 changes: 194 additions & 1 deletion src/AudioToolbox/AudioFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,9 @@ public AudioFileError WritePackets (bool useCache, int numBytes, AudioStreamPack
[DllImport (Constants.AudioToolboxLibrary)]
unsafe extern static OSStatus AudioFileCountUserData (AudioFileID handle, uint userData, int* count);

/// <summary>Get the number of user data for the specified chunk type.</summary>
/// <param name="userData">The fourcc of the ID whose count to retrieve.</param>
/// <returns>The number of user udata for the specified ID.</returns>
public int CountUserData (uint userData)
{
int count;
Expand All @@ -1170,29 +1173,219 @@ public int CountUserData (uint userData)
return -1;
}

/// <summary>Get the number of user data for the specified chunk type.</summary>
/// <param name="chunkType">The fourcc of the chunk.</param>
/// <returns>The number of user data for the specified chunk type.</returns>
public int CountUserData (AudioFileChunkType chunkType)
{
return CountUserData ((uint) chunkType);
}

[DllImport (Constants.AudioToolboxLibrary)]
unsafe extern static OSStatus AudioFileGetUserDataSize (AudioFileID audioFile, uint userDataID, int index, int* userDataSize);

/// <summary>Get the size of the specified user data.</summary>
/// <param name="userDataId">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <returns>Returns the (non-negative) size on success, otherwise -1.</returns>
public int GetUserDataSize (uint userDataId, int index)
{
int ds;

unsafe {
if (AudioFileGetUserDataSize (Handle, userDataId, index, &ds) == 0)
if (AudioFileGetUserDataSize (Handle, userDataId, index, &ds) != 0)
return -1;
}
return ds;
}

/// <summary>Get the size of the specified user data.</summary>
/// <param name="chunkType">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <returns>Returns the (non-negative) size on success, otherwise -1.</returns>
public int GetUserDataSize (AudioFileChunkType chunkType, int index)
{
return GetUserDataSize ((uint) chunkType, index);
}

#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
[DllImport (Constants.AudioToolboxLibrary)]
unsafe extern static OSStatus AudioFileGetUserDataSize64 (AudioFileID audioFile, uint userDataID, int index, ulong* userDataSize);

/// <summary>Get the 64-bit size of the specified user data.</summary>
/// <param name="userDataId">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="size">The retrieved 64-bit size of the specified user data.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
public AudioFileError GetUserDataSize (uint userDataId, int index, out ulong size)
{
size = 0;
unsafe {
return (AudioFileError) AudioFileGetUserDataSize64 (Handle, userDataId, index, (ulong*) Unsafe.AsPointer<ulong> (ref size));
}
}

/// <summary>Get the 64-bit size of the specified user data.</summary>
/// <param name="chunkType">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="size">The retrieved 64-bit size of the specified user data.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
public AudioFileError GetUserDataSize (AudioFileChunkType chunkType, int index, out ulong size)
{
return GetUserDataSize ((uint) chunkType, index, out size);
}

[DllImport (Constants.AudioToolboxLibrary)]
unsafe extern static OSStatus AudioFileGetUserData (AudioFileID audioFile, int userDataID, int index, int* userDataSize, IntPtr userData);

/// <summary>Get part of the data of a chunk in a file.</summary>
/// <param name="userDataID">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="size">On input the size of the memory <paramref name="userData" /> points to. On output the number of bytes written.</param>
/// <param name="userData">A pointer to memory where the data will be copied.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
#if XAMCORE_5_0
public AudioFileError GetUserData (int userDataID, int index, ref int size, IntPtr userData)
#else
public int GetUserData (int userDataID, int index, ref int size, IntPtr userData)
#endif
{
unsafe {
return AudioFileGetUserData (Handle, userDataID, index, (int*) Unsafe.AsPointer<int> (ref size), userData);
}
}

/// <summary>Get part of the data of a chunk in a file.</summary>
/// <param name="chunkType">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="size">On input the size of the memory <paramref name="userData" /> points to. On output the number of bytes written.</param>
/// <param name="userData">A pointer to memory where the data will be copied.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
public AudioFileError GetUserData (AudioFileChunkType chunkType, int index, ref int size, IntPtr userData)
{
return (AudioFileError) GetUserData ((int) chunkType, index, ref size, userData);
}

#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
[DllImport (Constants.AudioToolboxLibrary)]
unsafe extern static OSStatus AudioFileGetUserDataAtOffset (AudioFileID audioFile, uint userDataID, int index, long inOffset, int* userDataSize, IntPtr userData);

/// <summary>Get part of the data of a chunk in a file.</summary>
/// <param name="userDataId">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="offset">The offset from the first byte of the chunk of the data to get.</param>
/// <param name="size">On input the size of the memory <paramref name="userData" /> points to. On output the number of bytes written.</param>
/// <param name="userData">A pointer to memory where the data will be copied.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
public AudioFileError GetUserData (uint userDataId, int index, long offset, ref int size, IntPtr userData)
{
unsafe {
return (AudioFileError) AudioFileGetUserDataAtOffset (Handle, userDataId, index, offset, (int*) Unsafe.AsPointer<int> (ref size), userData);
}
}

/// <summary>Get part of the data of a chunk in a file.</summary>
/// <param name="chunkType">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="offset">The offset from the first byte of the chunk of the data to get.</param>
/// <param name="size">On input the size of the memory <paramref name="userData" /> points to. On output the number of bytes written.</param>
/// <param name="userData">A pointer to memory where the data will be copied.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
public AudioFileError GetUserData (AudioFileChunkType chunkType, int index, long offset, ref int size, IntPtr userData)
{
return GetUserData ((uint) chunkType, index, offset, ref size, userData);
}

/// <summary>Get part of the data of a chunk in a file.</summary>
/// <param name="userDataId">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="offset">The offset from the first byte of the chunk of the data to get.</param>
/// <param name="size">The number of bytes written into the byte array.</param>
/// <param name="data">An array of bytes where the data will be copied.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
public AudioFileError GetUserData (uint userDataId, int index, long offset, byte [] data, out int size)
{
size = data.Length;
unsafe {
fixed (byte* dataPtr = data)
return GetUserData (userDataId, index, offset, ref size, (IntPtr) dataPtr);
}
}

/// <summary>Get part of the data of a chunk in a file.</summary>
/// <param name="chunkType">The fourcc of the chunk.</param>
/// <param name="index">The index of the chunk if there are more than one chunk.</param>
/// <param name="offset">The offset from the first byte of the chunk of the data to get.</param>
/// <param name="size">The number of bytes written into the byte array.</param>
/// <param name="data">An array of bytes where the data will be copied.</param>
/// <returns>Returns <see cref="AudioFileError.Success" /> on success, otherwise an <see cref="AudioFileError" /> error code.</returns>
#if NET
[SupportedOSPlatform ("ios17.0")]
[SupportedOSPlatform ("tvos17.0")]
[SupportedOSPlatform ("maccatalyst17.0")]
[SupportedOSPlatform ("macos14.0")]
#else
[iOS (17, 0), TV (17, 0), MacCatalyst (17, 0), Mac (14, 0)]
#endif
public AudioFileError GetUserData (AudioFileChunkType chunkType, int index, long offset, byte [] data, out int size)
{
return GetUserData ((uint) chunkType, index, offset, data, out size);
}

[DllImport (Constants.AudioToolboxLibrary)]
extern static OSStatus AudioFileSetUserData (AudioFileID inAudioFile, int userDataID, int index, int userDataSize, IntPtr userData);

Expand Down
Loading

8 comments on commit 84bcea0

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.