PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/AudioUnit/ExtAudioFile.cs

https://github.com/kjpou1/maccore
C# | 424 lines | 314 code | 71 blank | 39 comment | 46 complexity | b0c24d025cd39771c17ebcfd0f34aa64 MD5 | raw file
Possible License(s): Apache-2.0
  1. //
  2. // ExtAudioFile.cs: ExtAudioFile wrapper class
  3. //
  4. // Authors:
  5. // AKIHIRO Uehara (u-akihiro@reinforce-lab.com)
  6. // Marek Safar (marek.safar@gmail.com)
  7. //
  8. // Copyright 2010 Reinforce Lab.
  9. // Copyright 2012 Xamarin Inc.
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. //
  31. using System;
  32. using System.Collections.Generic;
  33. using System.Text;
  34. using System.Runtime.InteropServices;
  35. using MonoMac.CoreFoundation;
  36. using MonoMac.AudioToolbox;
  37. namespace MonoMac.AudioUnit
  38. {
  39. public enum ExtAudioFileError
  40. {
  41. OK = 0,
  42. CodecUnavailableInputConsumed = -66559,
  43. CodecUnavailableInputNotConsumed = -66560,
  44. InvalidProperty = -66561,
  45. InvalidPropertySize = -66562,
  46. NonPCMClientFormat = -66563,
  47. InvalidChannelMap = -66564,
  48. InvalidOperationOrder = -66565,
  49. InvalidDataFormat = -66566,
  50. MaxPacketSizeUnknown = -66567,
  51. InvalidSeek = -66568,
  52. AsyncWriteTooLarge = -66569,
  53. AsyncWriteBufferOverflow = -66570,
  54. // Shared error codes
  55. NotOpenError = -38,
  56. EndOfFileError = -39,
  57. PositionError = -40,
  58. FileNotFoundError = -43
  59. }
  60. public class ExtAudioFile : IDisposable
  61. {
  62. IntPtr _extAudioFile;
  63. public uint? ClientMaxPacketSize {
  64. get {
  65. uint size = sizeof (uint);
  66. uint value;
  67. if (ExtAudioFileGetProperty (_extAudioFile, PropertyIDType.ClientMaxPacketSize, ref size, out value) != ExtAudioFileError.OK)
  68. return null;
  69. return value;
  70. }
  71. }
  72. public uint? FileMaxPacketSize {
  73. get {
  74. uint size = sizeof (uint);
  75. uint value;
  76. if (ExtAudioFileGetProperty (_extAudioFile, PropertyIDType.FileMaxPacketSize, ref size, out value) != ExtAudioFileError.OK)
  77. return null;
  78. return value;
  79. }
  80. }
  81. public IntPtr? AudioFile {
  82. get {
  83. uint size = (uint) Marshal.SizeOf (typeof (IntPtr));
  84. IntPtr value;
  85. if (ExtAudioFileGetProperty (_extAudioFile, PropertyIDType.AudioFile, ref size, out value) != ExtAudioFileError.OK)
  86. return null;
  87. return value;
  88. }
  89. }
  90. public AudioConverter AudioConverter {
  91. get {
  92. uint size = sizeof (uint);
  93. IntPtr value;
  94. if (ExtAudioFileGetProperty (_extAudioFile, PropertyIDType.AudioConverter, ref size, out value) != ExtAudioFileError.OK)
  95. return null;
  96. return new AudioConverter (value, false);
  97. }
  98. }
  99. public long FileLengthFrames {
  100. get {
  101. long length;
  102. uint size = sizeof (long);
  103. var err = ExtAudioFileGetProperty(_extAudioFile, PropertyIDType.FileLengthFrames, ref size, out length);
  104. if (err != 0)
  105. {
  106. throw new InvalidOperationException(String.Format("Error code:{0}", err));
  107. }
  108. return length;
  109. }
  110. }
  111. public AudioStreamBasicDescription FileDataFormat
  112. {
  113. get
  114. {
  115. AudioStreamBasicDescription dc = new AudioStreamBasicDescription();
  116. uint size = (uint)Marshal.SizeOf(typeof(AudioStreamBasicDescription));
  117. int err = ExtAudioFileGetProperty(_extAudioFile, PropertyIDType.FileDataFormat, ref size, ref dc);
  118. if (err != 0)
  119. {
  120. throw new InvalidOperationException(String.Format("Error code:{0}", err));
  121. }
  122. return dc;
  123. }
  124. }
  125. public AudioStreamBasicDescription ClientDataFormat
  126. {
  127. set
  128. {
  129. int err = ExtAudioFileSetProperty(_extAudioFile, PropertyIDType.ClientDataFormat,
  130. (uint)Marshal.SizeOf(value), ref value);
  131. if (err != 0)
  132. {
  133. throw new InvalidOperationException(String.Format("Error code:{0}", err));
  134. }
  135. }
  136. }
  137. private ExtAudioFile(IntPtr ptr)
  138. {
  139. _extAudioFile = ptr;
  140. }
  141. ~ExtAudioFile ()
  142. {
  143. Dispose (false);
  144. }
  145. public static ExtAudioFile OpenUrl (CFUrl url)
  146. {
  147. if (url == null)
  148. throw new ArgumentNullException ("url");
  149. ExtAudioFileError err;
  150. IntPtr ptr;
  151. unsafe {
  152. err = ExtAudioFileOpenUrl(url.Handle, (IntPtr)(&ptr));
  153. }
  154. if (err != 0)
  155. {
  156. throw new ArgumentException(String.Format("Error code:{0}", err));
  157. }
  158. if (ptr == IntPtr.Zero)
  159. {
  160. throw new InvalidOperationException("Can not get object instance");
  161. }
  162. return new ExtAudioFile(ptr);
  163. }
  164. public static ExtAudioFile CreateWithUrl (CFUrl url,
  165. AudioFileType fileType,
  166. AudioStreamBasicDescription inStreamDesc,
  167. //AudioChannelLayout channelLayout,
  168. AudioFileFlags flag)
  169. {
  170. if (url == null)
  171. throw new ArgumentNullException ("url");
  172. int err;
  173. IntPtr ptr = new IntPtr();
  174. unsafe {
  175. err = ExtAudioFileCreateWithUrl(url.Handle, fileType, ref inStreamDesc, IntPtr.Zero, (uint)flag,
  176. (IntPtr)(&ptr));
  177. }
  178. if (err != 0)
  179. {
  180. throw new ArgumentException(String.Format("Error code:{0}", err));
  181. }
  182. if (ptr == IntPtr.Zero)
  183. {
  184. throw new InvalidOperationException("Can not get object instance");
  185. }
  186. return new ExtAudioFile(ptr);
  187. }
  188. public static ExtAudioFileError WrapAudioFileID (IntPtr audioFileID, bool forWriting, out ExtAudioFile outAudioFile)
  189. {
  190. IntPtr ptr;
  191. ExtAudioFileError res;
  192. unsafe {
  193. res = ExtAudioFileWrapAudioFileID (audioFileID, forWriting, (IntPtr)(&ptr));
  194. }
  195. if (res != ExtAudioFileError.OK) {
  196. outAudioFile = null;
  197. return res;
  198. }
  199. outAudioFile = new ExtAudioFile (ptr);
  200. return res;
  201. }
  202. public void Seek(long frameOffset)
  203. {
  204. int err = ExtAudioFileSeek(_extAudioFile, frameOffset);
  205. if (err != 0)
  206. {
  207. throw new ArgumentException(String.Format("Error code:{0}", err));
  208. }
  209. }
  210. public long FileTell()
  211. {
  212. long frame = 0;
  213. int err = ExtAudioFileTell(_extAudioFile, ref frame);
  214. if (err != 0)
  215. {
  216. throw new ArgumentException(String.Format("Error code:{0}", err));
  217. }
  218. return frame;
  219. }
  220. [Obsolete ("Use overload with AudioBuffers")]
  221. public int Read(int numberFrames, AudioBufferList data)
  222. {
  223. if (data == null)
  224. throw new ArgumentNullException ("data");
  225. int err = ExtAudioFileRead(_extAudioFile, ref numberFrames, data);
  226. if (err != 0)
  227. {
  228. throw new ArgumentException(String.Format("Error code:{0}", err));
  229. }
  230. return numberFrames;
  231. }
  232. public uint Read (uint numberFrames, AudioBuffers audioBufferList, out ExtAudioFileError status)
  233. {
  234. if (audioBufferList == null)
  235. throw new ArgumentNullException ("audioBufferList");
  236. status = ExtAudioFileRead (_extAudioFile, ref numberFrames, (IntPtr) audioBufferList);
  237. return numberFrames;
  238. }
  239. [Obsolete ("Use overload with AudioBuffers")]
  240. public void WriteAsync(int numberFrames, AudioBufferList data)
  241. {
  242. int err = ExtAudioFileWriteAsync(_extAudioFile, numberFrames, data);
  243. if (err != 0) {
  244. throw new ArgumentException(String.Format("Error code:{0}", err));
  245. }
  246. }
  247. public ExtAudioFileError WriteAsync (uint numberFrames, AudioBuffers audioBufferList)
  248. {
  249. if (audioBufferList == null)
  250. throw new ArgumentNullException ("audioBufferList");
  251. return ExtAudioFileWriteAsync (_extAudioFile, numberFrames, (IntPtr) audioBufferList);
  252. }
  253. public ExtAudioFileError Write (uint numberFrames, AudioBuffers audioBufferList)
  254. {
  255. if (audioBufferList == null)
  256. throw new ArgumentNullException ("audioBufferList");
  257. return ExtAudioFileWrite (_extAudioFile, numberFrames, (IntPtr) audioBufferList);
  258. }
  259. public ExtAudioFileError SynchronizeAudioConverter ()
  260. {
  261. IntPtr value = IntPtr.Zero;
  262. return ExtAudioFileSetProperty (_extAudioFile, PropertyIDType.ConverterConfig,
  263. Marshal.SizeOf (value), value);
  264. }
  265. public void Dispose ()
  266. {
  267. Dispose (true);
  268. GC.SuppressFinalize (this);
  269. }
  270. protected virtual void Dispose (bool disposing)
  271. {
  272. if (_extAudioFile != IntPtr.Zero){
  273. ExtAudioFileDispose (_extAudioFile);
  274. _extAudioFile = IntPtr.Zero;
  275. }
  276. }
  277. #region Interop
  278. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileOpenURL")]
  279. static extern ExtAudioFileError ExtAudioFileOpenUrl(IntPtr inUrl, IntPtr outExtAudioFile); // caution
  280. [DllImport (MonoMac.Constants.AudioToolboxLibrary)]
  281. static extern ExtAudioFileError ExtAudioFileWrapAudioFileID (IntPtr inFileID, bool inForWriting, IntPtr outExtAudioFile);
  282. [Obsolete]
  283. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileRead")]
  284. static extern int ExtAudioFileRead(IntPtr inExtAudioFile, ref int ioNumberFrames, AudioBufferList ioData);
  285. [DllImport(MonoMac.Constants.AudioToolboxLibrary)]
  286. static extern ExtAudioFileError ExtAudioFileRead (IntPtr inExtAudioFile, ref uint ioNumberFrames, IntPtr ioData);
  287. [DllImport(MonoMac.Constants.AudioToolboxLibrary)]
  288. static extern ExtAudioFileError ExtAudioFileWrite (IntPtr inExtAudioFile, uint inNumberFrames, IntPtr ioData);
  289. [Obsolete]
  290. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileWriteAsync")]
  291. static extern int ExtAudioFileWriteAsync(IntPtr inExtAudioFile, int inNumberFrames, AudioBufferList ioData);
  292. [DllImport(MonoMac.Constants.AudioToolboxLibrary)]
  293. static extern ExtAudioFileError ExtAudioFileWriteAsync(IntPtr inExtAudioFile, uint inNumberFrames, IntPtr ioData);
  294. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileDispose")]
  295. static extern int ExtAudioFileDispose(IntPtr inExtAudioFile);
  296. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileSeek")]
  297. static extern int ExtAudioFileSeek(IntPtr inExtAudioFile, long inFrameOffset);
  298. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileTell")]
  299. static extern int ExtAudioFileTell(IntPtr inExtAudioFile, ref long outFrameOffset);
  300. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileCreateWithURL")]
  301. static extern int ExtAudioFileCreateWithUrl(IntPtr inURL,
  302. [MarshalAs(UnmanagedType.U4)] AudioFileType inFileType,
  303. ref AudioStreamBasicDescription inStreamDesc,
  304. IntPtr inChannelLayout, //AudioChannelLayout inChannelLayout, AudioChannelLayout results in compilation error (error code 134.)
  305. UInt32 flags,
  306. IntPtr outExtAudioFile);
  307. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileGetProperty")]
  308. static extern int ExtAudioFileGetProperty(
  309. IntPtr inExtAudioFile,
  310. PropertyIDType inPropertyID,
  311. ref uint ioPropertyDataSize,
  312. IntPtr outPropertyData);
  313. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileGetProperty")]
  314. static extern int ExtAudioFileGetProperty(
  315. IntPtr inExtAudioFile,
  316. PropertyIDType inPropertyID,
  317. ref uint ioPropertyDataSize,
  318. ref AudioStreamBasicDescription outPropertyData);
  319. [DllImport(MonoMac.Constants.AudioToolboxLibrary)]
  320. static extern ExtAudioFileError ExtAudioFileGetProperty (IntPtr inExtAudioFile, PropertyIDType inPropertyID, ref uint ioPropertyDataSize, out IntPtr outPropertyData);
  321. [DllImport(MonoMac.Constants.AudioToolboxLibrary)]
  322. static extern ExtAudioFileError ExtAudioFileGetProperty (IntPtr inExtAudioFile, PropertyIDType inPropertyID, ref uint ioPropertyDataSize, out long outPropertyData);
  323. [DllImport(MonoMac.Constants.AudioToolboxLibrary)]
  324. static extern ExtAudioFileError ExtAudioFileGetProperty (IntPtr inExtAudioFile, PropertyIDType inPropertyID, ref uint ioPropertyDataSize, out uint outPropertyData);
  325. [DllImport(MonoMac.Constants.AudioToolboxLibrary)]
  326. static extern ExtAudioFileError ExtAudioFileSetProperty (IntPtr inExtAudioFile, PropertyIDType inPropertyID, int ioPropertyDataSize, IntPtr outPropertyData);
  327. [DllImport(MonoMac.Constants.AudioToolboxLibrary, EntryPoint = "ExtAudioFileSetProperty")]
  328. static extern int ExtAudioFileSetProperty(
  329. IntPtr inExtAudioFile,
  330. PropertyIDType inPropertyID,
  331. uint ioPropertyDataSize,
  332. ref AudioStreamBasicDescription outPropertyData);
  333. enum PropertyIDType {
  334. FileDataFormat = 0x66666d74, // 'ffmt'
  335. //kExtAudioFileProperty_FileChannelLayout = 'fclo', // AudioChannelLayout
  336. ClientDataFormat = 0x63666d74, //'cfmt', // AudioStreamBasicDescription
  337. //kExtAudioFileProperty_ClientChannelLayout = 'cclo', // AudioChannelLayout
  338. CodecManufacturer = 0x636d616e, // 'cman'
  339. // read-only:
  340. AudioConverter = 0x61636e76, // 'acnv'
  341. AudioFile = 0x6166696c, // 'afil'
  342. FileMaxPacketSize = 0x666d7073, // 'fmps'
  343. ClientMaxPacketSize = 0x636d7073, // 'cmps'
  344. FileLengthFrames = 0x2366726d, // '#frm'
  345. // writable:
  346. ConverterConfig = 0x61636366, // 'accf'
  347. //kExtAudioFileProperty_IOBufferSizeBytes = 'iobs', // UInt32
  348. //kExtAudioFileProperty_IOBuffer = 'iobf', // void *
  349. //kExtAudioFileProperty_PacketTable = 'xpti' // AudioFilePacketTableInfo
  350. };
  351. #endregion
  352. }
  353. }