mixer.nim 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #
  2. # SDL_mixer: An audio mixer library based on the SDL library
  3. # Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
  4. #
  5. # This software is provided 'as-is', without any express or implied
  6. # warranty. In no event will the authors be held liable for any damages
  7. # arising from the use of this software.
  8. #
  9. # Permission is granted to anyone to use this software for any purpose,
  10. # including commercial applications, and to alter it and redistribute it
  11. # freely, subject to the following restrictions:
  12. #
  13. # 1. The origin of this software must not be misrepresented; you must not
  14. # claim that you wrote the original software. If you use this software
  15. # in a product, an acknowledgment in the product documentation would be
  16. # appreciated but is not required.
  17. # 2. Altered source versions must be plainly marked as such, and must not be
  18. # misrepresented as being the original software.
  19. # 3. This notice may not be removed or altered from any source distribution.
  20. #
  21. {.deadCodeElim: on.}
  22. # Dynamically link to the correct library for our system:
  23. when not defined(SDL_Static):
  24. when defined(windows):
  25. const LibName* = "SDL2_mixer.dll"
  26. elif defined(macosx):
  27. const LibName* = "libSDL2_mixer.dylib"
  28. else:
  29. const LibName* = "libSDL2_mixer(|-2.0).so(|.0)"
  30. else:
  31. static: echo "SDL_Static option is deprecated and will soon be removed. Instead please use --dynlibOverride:SDL2."
  32. when not defined(SDL_Static):
  33. {.push callConv:cdecl, dynlib: LibName.}
  34. import ../sdl2, audio
  35. when system.cpuEndian == littleEndian: # SDL_BYTEORDER == SDL_LIL_ENDIAN
  36. const
  37. MIX_DEFAULT_FORMAT* = AUDIO_S16LSB
  38. else:
  39. const
  40. MIX_DEFAULT_FORMAT* = AUDIO_S16MSB
  41. # Remove prefixes in our wrapper, we have modules in Nim:
  42. # These are not recognized by c2nim, but that's easy to fix:
  43. # This function gets the version of the dynamically linked SDL_mixer library.
  44. # it should NOT be used to fill a version structure, instead you should
  45. # use the SDL_MIXER_VERSION() macro.
  46. #
  47. proc linkedVersion*(): ptr SDL_version {.importc: "Mix_Linked_Version".}
  48. const
  49. MIX_INIT_FLAC* : cint = 0x00000001
  50. MIX_INIT_MOD* : cint = 0x00000002
  51. MIX_INIT_MODPLUG* : cint = 0x00000004
  52. MIX_INIT_MP3* : cint = 0x00000008
  53. MIX_INIT_OGG* : cint = 0x00000010
  54. MIX_INIT_FLUIDSYNTH* : cint = 0x00000020
  55. # Loads dynamic libraries and prepares them for use. Flags should be
  56. # one or more flags from MIX_InitFlags OR'd together.
  57. # It returns the flags successfully initialized, or 0 on failure.
  58. #
  59. proc init*(flags: cint): cint {.importc: "Mix_Init".}
  60. # Unloads libraries loaded with Mix_Init
  61. proc quit*() {.importc: "Mix_Quit".}
  62. # The default mixer has 8 simultaneous mixing channels
  63. const
  64. MIX_CHANNELS* = 8
  65. # Good default values for a PC soundcard
  66. const
  67. MIX_DEFAULT_FREQUENCY* = 22050
  68. MIX_DEFAULT_CHANNELS* = 2
  69. # Volume of a chunk
  70. const
  71. MIX_MAX_VOLUME* = 128
  72. # The internal format for an audio chunk
  73. type
  74. ChunkPtr* = ptr Chunk
  75. Chunk* = object
  76. allocated*: cint
  77. abuf*: ptr uint8
  78. alen*: uint32
  79. volume*: uint8 # Per-sample volume, 0-128
  80. # The different fading types supported
  81. type
  82. Fading* {.size: sizeof(cint).} = enum
  83. MIX_NO_FADING, MIX_FADING_OUT, MIX_FADING_IN
  84. MusicType* {.size: sizeof(cint).} = enum
  85. MUS_NONE, MUS_CMD, MUS_WAV, MUS_MOD, MUS_MID, MUS_OGG, MUS_MP3, MUS_MP3_MAD,
  86. MUS_FLAC, MUS_MODPLUG
  87. # The internal format for a music chunk interpreted via mikmod
  88. type
  89. MusicPtr* = ptr Music
  90. Music* = object
  91. # Open the mixer with a certain audio format
  92. proc openAudio*(frequency: cint; format: uint16; channels: cint;
  93. chunksize: cint): cint {.importc: "Mix_OpenAudio".}
  94. # Dynamically change the number of channels managed by the mixer.
  95. # If decreasing the number of channels, the upper channels are
  96. # stopped.
  97. # This function returns the new number of allocated channels.
  98. #
  99. proc allocateChannels*(numchans: cint): cint {.
  100. importc: "Mix_AllocateChannels".}
  101. # Find out what the actual audio device parameters are.
  102. # This function returns 1 if the audio has been opened, 0 otherwise.
  103. #
  104. proc querySpec*(frequency: ptr cint; format: ptr uint16; channels: ptr cint): cint {.
  105. importc: "Mix_QuerySpec".}
  106. # Load a wave file or a music (.mod .s3m .it .xm) file
  107. proc loadWAV_RW*(src: RWopsPtr; freesrc: cint): ptr Chunk {.importc: "Mix_LoadWAV_RW".}
  108. template loadWAV*(file: untyped): untyped =
  109. loadWAV_RW(rwFromFile(file, "rb"), 1)
  110. proc loadMUS*(file: cstring): ptr Music {.importc: "Mix_LoadMUS".}
  111. # Load a music file from an SDL_RWops object (Ogg and MikMod specific currently)
  112. # Matt Campbell (matt@campbellhome.dhs.org) April 2000
  113. proc loadMUS_RW*(src: RWopsPtr; freesrc: cint): ptr Music {.
  114. importc: "Mix_LoadMUS_RW".}
  115. # Load a music file from an SDL_RWops object assuming a specific format
  116. proc loadMUSType_RW*(src: RWopsPtr; `type`: MusicType; freesrc: cint): ptr Music {.
  117. importc: "Mix_LoadMUSType_RW".}
  118. # Load a wave file of the mixer format from a memory buffer
  119. proc quickLoad_WAV*(mem: ptr uint8): ptr Chunk {.importc: "Mix_QuickLoad_WAV".}
  120. # Load raw audio data of the mixer format from a memory buffer
  121. proc quickLoad_RAW*(mem: ptr uint8; len: uint32): ptr Chunk {.importc: "Mix_QuickLoad_RAW".}
  122. # Free an audio chunk previously loaded
  123. proc freeChunk*(chunk: ptr Chunk) {.importc: "Mix_FreeChunk".}
  124. proc freeMusic*(music: ptr Music) {.importc: "Mix_FreeMusic".}
  125. # Get a list of chunk/music decoders that this build of SDL_mixer provides.
  126. # This list can change between builds AND runs of the program, if external
  127. # libraries that add functionality become available.
  128. # You must successfully call Mix_OpenAudio() before calling these functions.
  129. # This API is only available in SDL_mixer 1.2.9 and later.
  130. #
  131. # // usage...
  132. # int i;
  133. # const int total = Mix_GetNumChunkDecoders();
  134. # for (i = 0; i < total; i++)
  135. # printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i));
  136. #
  137. # Appearing in this list doesn't promise your specific audio file will
  138. # decode...but it's handy to know if you have, say, a functioning Timidity
  139. # install.
  140. #
  141. # These return values are static, read-only data; do not modify or free it.
  142. # The pointers remain valid until you call Mix_CloseAudio().
  143. #
  144. proc getNumChunkDecoders*(): cint {.importc: "Mix_GetNumChunkDecoders".}
  145. proc getChunkDecoder*(index: cint): cstring {.importc: "Mix_GetChunkDecoder".}
  146. proc getNumMusicDecoders*(): cint {.importc: "Mix_GetNumMusicDecoders".}
  147. proc getMusicDecoder*(index: cint): cstring {.importc: "Mix_GetMusicDecoder".}
  148. # Find out the music format of a mixer music, or the currently playing
  149. # music, if 'music' is NULL.
  150. #
  151. proc getMusicType*(music: ptr Music): MusicType {.importc: "Mix_GetMusicType".}
  152. # Set a function that is called after all mixing is performed.
  153. # This can be used to provide real-time visual display of the audio stream
  154. # or add a custom mixer filter for the stream data.
  155. #
  156. proc setPostMix*(mix_func: proc (udata: pointer; stream: ptr uint8;
  157. len: cint) {.cdecl.}; arg: pointer) {.importc: "Mix_SetPostMix".}
  158. # Add your own music player or additional mixer function.
  159. # If 'mix_func' is NULL, the default music player is re-enabled.
  160. #
  161. proc hookMusic*(mix_func: proc (udata: pointer; stream: ptr uint8; len: cint) {.
  162. cdecl.}; arg: pointer) {.importc: "Mix_HookMusic".}
  163. # Add your own callback when the music has finished playing.
  164. # This callback is only called if the music finishes naturally.
  165. #
  166. proc hookMusicFinished*(music_finished: proc () {.cdecl.}) {.importc: "Mix_HookMusicFinished".}
  167. # Get a pointer to the user data for the current music hook
  168. proc getMusicHookData*(): pointer {.importc: "Mix_GetMusicHookData".}
  169. #
  170. # Add your own callback when a channel has finished playing. NULL
  171. # to disable callback. The callback may be called from the mixer's audio
  172. # callback or it could be called as a result of Mix_HaltChannel(), etc.
  173. # do not call SDL_LockAudio() from this callback; you will either be
  174. # inside the audio callback, or SDL_mixer will explicitly lock the audio
  175. # before calling your callback.
  176. #
  177. proc channelFinished*(channel_finished: proc (channel: cint) {.cdecl.}) {.importc: "Mix_ChannelFinished".}
  178. # Special Effects API by ryan c. gordon. (icculus@icculus.org)
  179. const
  180. MIX_CHANNEL_POST* = - 2
  181. # This is the format of a special effect callback:
  182. #
  183. # myeffect(int chan, void *stream, int len, void *udata);
  184. #
  185. # (chan) is the channel number that your effect is affecting. (stream) is
  186. # the buffer of data to work upon. (len) is the size of (stream), and
  187. # (udata) is a user-defined bit of data, which you pass as the last arg of
  188. # Mix_RegisterEffect(), and is passed back unmolested to your callback.
  189. # Your effect changes the contents of (stream) based on whatever parameters
  190. # are significant, or just leaves it be, if you prefer. You can do whatever
  191. # you like to the buffer, though, and it will continue in its changed state
  192. # down the mixing pipeline, through any other effect functions, then finally
  193. # to be mixed with the rest of the channels and music for the final output
  194. # stream.
  195. #
  196. # DO NOT EVER call SDL_LockAudio() from your callback function!
  197. #
  198. type
  199. Mix_EffectFunc_t* = proc (chan: cint; stream: pointer; len: cint;
  200. udata: pointer) {.cdecl.}
  201. #
  202. # This is a callback that signifies that a channel has finished all its
  203. # loops and has completed playback. This gets called if the buffer
  204. # plays out normally, or if you call Mix_HaltChannel(), implicitly stop
  205. # a channel via Mix_AllocateChannels(), or unregister a callback while
  206. # it's still playing.
  207. #
  208. # DO NOT EVER call SDL_LockAudio() from your callback function!
  209. #
  210. type
  211. Mix_EffectDone_t* = proc (chan: cint; udata: pointer) {.cdecl.}
  212. # Register a special effect function. At mixing time, the channel data is
  213. # copied into a buffer and passed through each registered effect function.
  214. # After it passes through all the functions, it is mixed into the final
  215. # output stream. The copy to buffer is performed once, then each effect
  216. # function performs on the output of the previous effect. Understand that
  217. # this extra copy to a buffer is not performed if there are no effects
  218. # registered for a given chunk, which saves CPU cycles, and any given
  219. # effect will be extra cycles, too, so it is crucial that your code run
  220. # fast. Also note that the data that your function is given is in the
  221. # format of the sound device, and not the format you gave to Mix_OpenAudio(),
  222. # although they may in reality be the same. This is an unfortunate but
  223. # necessary speed concern. Use Mix_QuerySpec() to determine if you can
  224. # handle the data before you register your effect, and take appropriate
  225. # actions.
  226. # You may also specify a callback (Mix_EffectDone_t) that is called when
  227. # the channel finishes playing. This gives you a more fine-grained control
  228. # than Mix_ChannelFinished(), in case you need to free effect-specific
  229. # resources, etc. If you don't need this, you can specify NULL.
  230. # You may set the callbacks before or after calling Mix_PlayChannel().
  231. # Things like Mix_SetPanning() are just internal special effect functions,
  232. # so if you are using that, you've already incurred the overhead of a copy
  233. # to a separate buffer, and that these effects will be in the queue with
  234. # any functions you've registered. The list of registered effects for a
  235. # channel is reset when a chunk finishes playing, so you need to explicitly
  236. # set them with each call to Mix_PlayChannel*().
  237. # You may also register a special effect function that is to be run after
  238. # final mixing occurs. The rules for these callbacks are identical to those
  239. # in Mix_RegisterEffect, but they are run after all the channels and the
  240. # music have been mixed into a single stream, whereas channel-specific
  241. # effects run on a given channel before any other mixing occurs. These
  242. # global effect callbacks are call "posteffects". Posteffects only have
  243. # their Mix_EffectDone_t function called when they are unregistered (since
  244. # the main output stream is never "done" in the same sense as a channel).
  245. # You must unregister them manually when you've had enough. Your callback
  246. # will be told that the channel being mixed is (MIX_CHANNEL_POST) if the
  247. # processing is considered a posteffect.
  248. #
  249. # After all these effects have finished processing, the callback registered
  250. # through Mix_SetPostMix() runs, and then the stream goes to the audio
  251. # device.
  252. #
  253. # DO NOT EVER call SDL_LockAudio() from your callback function!
  254. #
  255. # returns zero if error (no such channel), nonzero if added.
  256. # Error messages can be retrieved from Mix_GetError().
  257. #
  258. proc registerEffect*(chan: cint; f: Mix_EffectFunc_t; d: Mix_EffectDone_t;
  259. arg: pointer): cint {.importc: "Mix_RegisterEffect".}
  260. # You may not need to call this explicitly, unless you need to stop an
  261. # effect from processing in the middle of a chunk's playback.
  262. # Posteffects are never implicitly unregistered as they are for channels,
  263. # but they may be explicitly unregistered through this function by
  264. # specifying MIX_CHANNEL_POST for a channel.
  265. # returns zero if error (no such channel or effect), nonzero if removed.
  266. # Error messages can be retrieved from Mix_GetError().
  267. #
  268. proc unregisterEffect*(channel: cint; f: Mix_EffectFunc_t): cint {.importc: "Mix_UnregisterEffect".}
  269. # You may not need to call this explicitly, unless you need to stop all
  270. # effects from processing in the middle of a chunk's playback. Note that
  271. # this will also shut off some internal effect processing, since
  272. # Mix_SetPanning() and others may use this API under the hood. This is
  273. # called internally when a channel completes playback.
  274. # Posteffects are never implicitly unregistered as they are for channels,
  275. # but they may be explicitly unregistered through this function by
  276. # specifying MIX_CHANNEL_POST for a channel.
  277. # returns zero if error (no such channel), nonzero if all effects removed.
  278. # Error messages can be retrieved from Mix_GetError().
  279. #
  280. proc unregisterAllEffects*(channel: cint): cint {.importc: "Mix_UnregisterAllEffects".}
  281. const
  282. MIX_EFFECTSMAXSPEED* = "MIX_EFFECTSMAXSPEED"
  283. #
  284. # These are the internally-defined mixing effects. They use the same API that
  285. # effects defined in the application use, but are provided here as a
  286. # convenience. Some effects can reduce their quality or use more memory in
  287. # the name of speed; to enable this, make sure the environment variable
  288. # MIX_EFFECTSMAXSPEED (see above) is defined before you call
  289. # Mix_OpenAudio().
  290. #
  291. # Set the panning of a channel. The left and right channels are specified
  292. # as integers between 0 and 255, quietest to loudest, respectively.
  293. #
  294. # Technically, this is just individual volume control for a sample with
  295. # two (stereo) channels, so it can be used for more than just panning.
  296. # If you want real panning, call it like this:
  297. #
  298. # Mix_SetPanning(channel, left, 255 - left);
  299. #
  300. # ...which isn't so hard.
  301. #
  302. # Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
  303. # the panning will be done to the final mixed stream before passing it on
  304. # to the audio device.
  305. #
  306. # This uses the Mix_RegisterEffect() API internally, and returns without
  307. # registering the effect function if the audio device is not configured
  308. # for stereo output. Setting both (left) and (right) to 255 causes this
  309. # effect to be unregistered, since that is the data's normal state.
  310. #
  311. # returns zero if error (no such channel or Mix_RegisterEffect() fails),
  312. # nonzero if panning effect enabled. Note that an audio device in mono
  313. # mode is a no-op, but this call will return successful in that case.
  314. # Error messages can be retrieved from Mix_GetError().
  315. #
  316. proc setPanning*(channel: cint; left: uint8; right: uint8): cint {.importc: "Mix_SetPanning".}
  317. # Set the position of a channel. (angle) is an integer from 0 to 360, that
  318. # specifies the location of the sound in relation to the listener. (angle)
  319. # will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260).
  320. # Angle 0 is due north, and rotates clockwise as the value increases.
  321. # For efficiency, the precision of this effect may be limited (angles 1
  322. # through 7 might all produce the same effect, 8 through 15 are equal, etc).
  323. # (distance) is an integer between 0 and 255 that specifies the space
  324. # between the sound and the listener. The larger the number, the further
  325. # away the sound is. Using 255 does not guarantee that the channel will be
  326. # culled from the mixing process or be completely silent. For efficiency,
  327. # the precision of this effect may be limited (distance 0 through 5 might
  328. # all produce the same effect, 6 through 10 are equal, etc). Setting (angle)
  329. # and (distance) to 0 unregisters this effect, since the data would be
  330. # unchanged.
  331. #
  332. # If you need more precise positional audio, consider using OpenAL for
  333. # spatialized effects instead of SDL_mixer. This is only meant to be a
  334. # basic effect for simple "3D" games.
  335. #
  336. # If the audio device is configured for mono output, then you won't get
  337. # any effectiveness from the angle; however, distance attenuation on the
  338. # channel will still occur. While this effect will function with stereo
  339. # voices, it makes more sense to use voices with only one channel of sound,
  340. # so when they are mixed through this effect, the positioning will sound
  341. # correct. You can convert them to mono through SDL before giving them to
  342. # the mixer in the first place if you like.
  343. #
  344. # Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
  345. # the positioning will be done to the final mixed stream before passing it
  346. # on to the audio device.
  347. #
  348. # This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning().
  349. #
  350. # returns zero if error (no such channel or Mix_RegisterEffect() fails),
  351. # nonzero if position effect is enabled.
  352. # Error messages can be retrieved from Mix_GetError().
  353. #
  354. proc setPosition*(channel: cint; angle: int16; distance: uint8): cint {.importc: "Mix_SetPosition".}
  355. # Set the "distance" of a channel. (distance) is an integer from 0 to 255
  356. # that specifies the location of the sound in relation to the listener.
  357. # Distance 0 is overlapping the listener, and 255 is as far away as possible
  358. # A distance of 255 does not guarantee silence; in such a case, you might
  359. # want to try changing the chunk's volume, or just cull the sample from the
  360. # mixing process with Mix_HaltChannel().
  361. # For efficiency, the precision of this effect may be limited (distances 1
  362. # through 7 might all produce the same effect, 8 through 15 are equal, etc).
  363. # (distance) is an integer between 0 and 255 that specifies the space
  364. # between the sound and the listener. The larger the number, the further
  365. # away the sound is.
  366. # Setting (distance) to 0 unregisters this effect, since the data would be
  367. # unchanged.
  368. # If you need more precise positional audio, consider using OpenAL for
  369. # spatialized effects instead of SDL_mixer. This is only meant to be a
  370. # basic effect for simple "3D" games.
  371. #
  372. # Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
  373. # the distance attenuation will be done to the final mixed stream before
  374. # passing it on to the audio device.
  375. #
  376. # This uses the Mix_RegisterEffect() API internally.
  377. #
  378. # returns zero if error (no such channel or Mix_RegisterEffect() fails),
  379. # nonzero if position effect is enabled.
  380. # Error messages can be retrieved from Mix_GetError().
  381. #
  382. proc setDistance*(channel: cint; distance: uint8): cint {.importc: "Mix_SetDistance".}
  383. #
  384. # !!! FIXME : Haven't implemented, since the effect goes past the
  385. # end of the sound buffer. Will have to think about this.
  386. # --ryan.
  387. #
  388. when false:
  389. # Causes an echo effect to be mixed into a sound. (echo) is the amount
  390. # of echo to mix. 0 is no echo, 255 is infinite (and probably not
  391. # what you want).
  392. #
  393. # Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and
  394. # the reverbing will be done to the final mixed stream before passing it on
  395. # to the audio device.
  396. #
  397. # This uses the Mix_RegisterEffect() API internally. If you specify an echo
  398. # of zero, the effect is unregistered, as the data is already in that state.
  399. #
  400. # returns zero if error (no such channel or Mix_RegisterEffect() fails),
  401. # nonzero if reversing effect is enabled.
  402. # Error messages can be retrieved from Mix_GetError().
  403. #
  404. proc setReverb*(channel: cint; echo: uint8): cint {.importc: "Mix_SetReverb".}
  405. # Causes a channel to reverse its stereo. This is handy if the user has his
  406. # speakers hooked up backwards, or you would like to have a minor bit of
  407. # psychedelia in your sound code. :) Calling this function with (flip)
  408. # set to non-zero reverses the chunks's usual channels. If (flip) is zero,
  409. # the effect is unregistered.
  410. #
  411. # This uses the Mix_RegisterEffect() API internally, and thus is probably
  412. # more CPU intensive than having the user just plug in his speakers
  413. # correctly. Mix_SetReverseStereo() returns without registering the effect
  414. # function if the audio device is not configured for stereo output.
  415. #
  416. # If you specify MIX_CHANNEL_POST for (channel), then this the effect is used
  417. # on the final mixed stream before sending it on to the audio device (a
  418. # posteffect).
  419. #
  420. # returns zero if error (no such channel or Mix_RegisterEffect() fails),
  421. # nonzero if reversing effect is enabled. Note that an audio device in mono
  422. # mode is a no-op, but this call will return successful in that case.
  423. # Error messages can be retrieved from Mix_GetError().
  424. #
  425. proc setReverseStereo*(channel: cint; flip: cint): cint {.importc: "Mix_SetReverseStereo".}
  426. # end of effects API. --ryan.
  427. # Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate
  428. # them dynamically to the next sample if requested with a -1 value below.
  429. # Returns the number of reserved channels.
  430. #
  431. proc reserveChannels*(num: cint): cint {.importc: "Mix_ReserveChannels".}
  432. # Channel grouping functions
  433. # Attach a tag to a channel. A tag can be assigned to several mixer
  434. # channels, to form groups of channels.
  435. # If 'tag' is -1, the tag is removed (actually -1 is the tag used to
  436. # represent the group of all the channels).
  437. # Returns true if everything was OK.
  438. #
  439. proc groupChannel*(which: cint; tag: cint): cint {.importc: "Mix_GroupChannel".}
  440. # Assign several consecutive channels to a group
  441. proc groupChannels*(`from`: cint; to: cint; tag: cint): cint {.importc: "Mix_GroupChannels".}
  442. # Finds the first available channel in a group of channels,
  443. # returning -1 if none are available.
  444. #
  445. proc groupAvailable*(tag: cint): cint {.importc: "Mix_GroupAvailable".}
  446. # Returns the number of channels in a group. This is also a subtle
  447. # way to get the total number of channels when 'tag' is -1
  448. #
  449. proc groupCount*(tag: cint): cint {.importc: "Mix_GroupCount".}
  450. # Finds the "oldest" sample playing in a group of channels
  451. proc groupOldest*(tag: cint): cint {.importc: "Mix_GroupOldest".}
  452. # Finds the "most recent" (i.e. last) sample playing in a group of channels
  453. proc groupNewer*(tag: cint): cint {.importc: "Mix_GroupNewer".}
  454. # Play an audio chunk on a specific channel.
  455. # If the specified channel is -1, play on the first free channel.
  456. # If 'loops' is greater than zero, loop the sound that many times.
  457. # If 'loops' is -1, loop inifinitely (~65000 times).
  458. # The sound is played at most 'ticks' milliseconds. If -1, play forever.
  459. # Returns which channel was used to play the sound.
  460. #
  461. proc playChannelTimed*(channel: cint; chunk: ptr Chunk; loops: cint;
  462. ticks: cint): cint {.importc: "Mix_PlayChannelTimed".}
  463. # The same as above, but the sound is played forever
  464. template playChannel*(channel, chunk, loops: untyped): untyped =
  465. playChannelTimed(channel, chunk, loops, - 1)
  466. proc playMusic*(music: ptr Music; loops: cint): cint {.importc: "Mix_PlayMusic".}
  467. # Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions
  468. proc fadeInMusic*(music: ptr Music; loops: cint; ms: cint): cint {.importc: "Mix_FadeInMusic".}
  469. proc fadeInMusicPos*(music: ptr Music; loops: cint; ms: cint;
  470. position: cdouble): cint {.importc: "Mix_FadeInMusicPos".}
  471. template fadeInChannel*(channel, chunk, loops, ms: untyped): untyped =
  472. fadeInChannelTimed(channel, chunk, loops, ms, - 1)
  473. proc fadeInChannelTimed*(channel: cint; chunk: ptr Chunk; loops: cint;
  474. ms: cint; ticks: cint): cint {.importc: "Mix_FadeInChannelTimed".}
  475. # Set the volume in the range of 0-128 of a specific channel or chunk.
  476. # If the specified channel is -1, set volume for all channels.
  477. # Returns the original volume.
  478. # If the specified volume is -1, just return the current volume.
  479. #
  480. proc volume*(channel: cint; volume: cint): cint {.importc: "Mix_Volume".}
  481. proc volumeChunk*(chunk: ptr Chunk; volume: cint): cint {.importc: "Mix_VolumeChunk".}
  482. proc volumeMusic*(volume: cint): cint {.importc: "Mix_VolumeMusic".}
  483. # Halt playing of a particular channel
  484. proc haltChannel*(channel: cint): cint {.importc: "Mix_HaltChannel".}
  485. proc haltGroup*(tag: cint): cint {.importc: "Mix_HaltGroup".}
  486. proc haltMusic*(): cint {.importc: "Mix_HaltMusic".}
  487. # Change the expiration delay for a particular channel.
  488. # The sample will stop playing after the 'ticks' milliseconds have elapsed,
  489. # or remove the expiration if 'ticks' is -1
  490. #
  491. proc expireChannel*(channel: cint; ticks: cint): cint {.importc: "Mix_ExpireChannel".}
  492. # Halt a channel, fading it out progressively till it's silent
  493. # The ms parameter indicates the number of milliseconds the fading
  494. # will take.
  495. #
  496. proc fadeOutChannel*(which: cint; ms: cint): cint {.importc: "Mix_FadeOutChannel".}
  497. proc fadeOutGroup*(tag: cint; ms: cint): cint {.importc: "Mix_FadeOutGroup".}
  498. proc fadeOutMusic*(ms: cint): cint {.importc: "Mix_FadeOutMusic".}
  499. # Query the fading status of a channel
  500. proc fadingMusic*(): Fading {.importc: "Mix_FadingMusic".}
  501. proc fadingChannel*(which: cint): Fading {.importc: "Mix_FadingChannel".}
  502. # Pause/Resume a particular channel
  503. proc pause*(channel: cint) {.importc: "Mix_Pause".}
  504. proc resume*(channel: cint) {.importc: "Mix_Resume".}
  505. proc paused*(channel: cint): cint {.importc: "Mix_Paused".}
  506. # Pause/Resume the music stream
  507. proc pauseMusic*() {.importc: "Mix_PauseMusic".}
  508. proc resumeMusic*() {.importc: "Mix_ResumeMusic".}
  509. proc rewindMusic*() {.importc: "Mix_RewindMusic".}
  510. proc pausedMusic*(): cint {.importc: "Mix_PausedMusic".}
  511. # Set the current position in the music stream.
  512. # This returns 0 if successful, or -1 if it failed or isn't implemented.
  513. # This function is only implemented for MOD music formats (set pattern
  514. # order number) and for OGG, FLAC, MP3_MAD, and MODPLUG music (set
  515. # position in seconds), at the moment.
  516. #
  517. proc setMusicPosition*(position: cdouble): cint {.importc: "Mix_SetMusicPosition".}
  518. # Check the status of a specific channel.
  519. # If the specified channel is -1, check all channels.
  520. #
  521. proc playing*(channel: cint): cint {.importc: "Mix_Playing".}
  522. proc playingMusic*(): cint {.importc: "Mix_PlayingMusic".}
  523. # Stop music and set external music playback command
  524. proc setMusicCMD*(command: cstring): cint {.importc: "Mix_SetMusicCMD".}
  525. # Synchro value is set by MikMod from modules while playing
  526. proc setSynchroValue*(value: cint): cint {.importc: "Mix_SetSynchroValue".}
  527. proc getSynchroValue*(): cint {.importc: "Mix_GetSynchroValue".}
  528. # Set/Get/Iterate SoundFonts paths to use by supported MIDI backends
  529. proc setSoundFonts*(paths: cstring): cint {.
  530. importc: "Mix_SetSoundFonts".}
  531. proc getSoundFonts*(): cstring {.importc: "Mix_GetSoundFonts".}
  532. proc eachSoundFont*(function: proc (a2: cstring; a3: pointer): cint {.cdecl.};
  533. data: pointer): cint {.importc: "Mix_EachSoundFont".}
  534. # Get the Chunk currently associated with a mixer channel
  535. # Returns NULL if it's an invalid channel, or there's no chunk associated.
  536. #
  537. proc getChunk*(channel: cint): ptr Chunk {.importc: "Mix_GetChunk".}
  538. # Close the mixer, halting all playing audio
  539. proc closeAudio*() {.importc: "Mix_CloseAudio".}
  540. when not defined(SDL_Static):
  541. {.pop.}