audio.go 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. // Audio extension
  2. package al
  3. /*
  4. #cgo pkg-config: allegro_audio-5
  5. #cgo CFLAGS: -I/usr/local/include -DALLEGRO_UNSTABLE
  6. #cgo linux LDFLAGS: -lc_nonshared
  7. #include <stdlib.h>
  8. #include <allegro5/allegro.h>
  9. #include <allegro5/allegro_audio.h>
  10. #include "helpers.h"
  11. */
  12. import "C"
  13. import "runtime"
  14. import "unsafe"
  15. // User event type emitted when a stream fragment is ready to be
  16. // refilled with more audio data.
  17. const (
  18. EVENT_AUDIO_STREAM_FRAGMENT = C.ALLEGRO_EVENT_AUDIO_STREAM_FRAGMENT
  19. EVENT_AUDIO_STREAM_FINISHED = C.ALLEGRO_EVENT_AUDIO_STREAM_FINISHED
  20. EVENT_AUDIO_RECORDER_FRAGMENT = C.ALLEGRO_EVENT_AUDIO_RECORDER_FRAGMENT
  21. )
  22. // Converts wrapper Event pointer to C Allegro audio recorder event
  23. func (self *Event) AUDIO_RECORDER_EVENT() *C.ALLEGRO_AUDIO_RECORDER_EVENT {
  24. return (*C.ALLEGRO_AUDIO_RECORDER_EVENT)(self.toPointer())
  25. }
  26. type AudioRecorderEvent C.ALLEGRO_AUDIO_RECORDER_EVENT
  27. type AudioDepth int
  28. // Converts an AudioDepth to an ALLEGRO_AUDIO_DEPTH
  29. func (self AudioDepth) toC() C.ALLEGRO_AUDIO_DEPTH {
  30. return C.ALLEGRO_AUDIO_DEPTH(self)
  31. }
  32. const (
  33. AUDIO_DEPTH_INT8 AudioDepth = C.ALLEGRO_AUDIO_DEPTH_INT8
  34. AUDIO_DEPTH_INT16 AudioDepth = C.ALLEGRO_AUDIO_DEPTH_INT16
  35. AUDIO_DEPTH_INT24 AudioDepth = C.ALLEGRO_AUDIO_DEPTH_INT24
  36. AUDIO_DEPTH_UINT8 AudioDepth = C.ALLEGRO_AUDIO_DEPTH_UINT8
  37. AUDIO_DEPTH_UINT16 AudioDepth = C.ALLEGRO_AUDIO_DEPTH_UINT16
  38. AUDIO_DEPTH_UINT24 AudioDepth = C.ALLEGRO_AUDIO_DEPTH_UINT24
  39. AUDIO_DEPTH_FLOAT32 AudioDepth = C.ALLEGRO_AUDIO_DEPTH_FLOAT32
  40. AUDIO_DEPTH_UNSIGNED AudioDepth = C.ALLEGRO_AUDIO_DEPTH_UNSIGNED
  41. )
  42. /*
  43. Speaker configuration (mono, stereo, 2.1, 3, etc). With regards to
  44. * behavior, most of this code makes no distinction between, say, 4.1 and
  45. * 5 speaker setups.. they both have 5 "channels". However, users would
  46. * like the distinction, and later when the higher-level stuff is added,
  47. * the differences will become more important. (v>>4)+(v&0xF) should yield
  48. * the total channel count.
  49. */
  50. type ChannelConf int
  51. // Converts a ChannelConf to a C.ALLEGRO_CHANNEL_CONF
  52. func (self ChannelConf) toC() C.ALLEGRO_CHANNEL_CONF {
  53. return (C.ALLEGRO_CHANNEL_CONF)(self)
  54. }
  55. const (
  56. CHANNEL_CONF_1 ChannelConf = C.ALLEGRO_CHANNEL_CONF_1
  57. CHANNEL_CONF_2 ChannelConf = C.ALLEGRO_CHANNEL_CONF_2
  58. CHANNEL_CONF_3 ChannelConf = C.ALLEGRO_CHANNEL_CONF_3
  59. CHANNEL_CONF_4 ChannelConf = C.ALLEGRO_CHANNEL_CONF_4
  60. CHANNEL_CONF_5_1 ChannelConf = C.ALLEGRO_CHANNEL_CONF_5_1
  61. CHANNEL_CONF_6_1 ChannelConf = C.ALLEGRO_CHANNEL_CONF_6_1
  62. CHANNEL_CONF_7_1 ChannelConf = C.ALLEGRO_CHANNEL_CONF_7_1
  63. MAX_CHANNELS ChannelConf = C.ALLEGRO_MAX_CHANNELS
  64. )
  65. type PlayMode int
  66. // Converts a PlayMode to a C.ALLEGRO_PLAYMODE
  67. func (self PlayMode) toC() C.ALLEGRO_PLAYMODE {
  68. return (C.ALLEGRO_PLAYMODE)(self)
  69. }
  70. const (
  71. PLAYMODE_ONCE PlayMode = C.ALLEGRO_PLAYMODE_ONCE
  72. PLAYMODE_LOOP PlayMode = C.ALLEGRO_PLAYMODE_LOOP
  73. PLAYMODE_BIDIR PlayMode = C.ALLEGRO_PLAYMODE_BIDIR
  74. )
  75. type MixerQuality int
  76. // Converts a MixerQuaklity to a C.ALLEGRO_MIXER_QUALITY
  77. func (self MixerQuality) toC() C.ALLEGRO_MIXER_QUALITY {
  78. return (C.ALLEGRO_MIXER_QUALITY)(self)
  79. }
  80. const (
  81. MIXER_QUALITY_POINT MixerQuality = C.ALLEGRO_MIXER_QUALITY_POINT
  82. MIXER_QUALITY_LINEAR MixerQuality = C.ALLEGRO_MIXER_QUALITY_LINEAR
  83. MIXER_QUALITY_CUBIC MixerQuality = C.ALLEGRO_MIXER_QUALITY_CUBIC
  84. )
  85. const AUDIO_PAN_NONE = -1000.0
  86. type AudioEventType int
  87. type Sample struct {
  88. handle *C.ALLEGRO_SAMPLE
  89. }
  90. type SampleId C.ALLEGRO_SAMPLE_ID
  91. func (self *SampleId) toC() *C.ALLEGRO_SAMPLE_ID {
  92. return (*C.ALLEGRO_SAMPLE_ID)(self)
  93. }
  94. type SampleInstance struct {
  95. handle *C.ALLEGRO_SAMPLE_INSTANCE
  96. }
  97. type AudioStream struct {
  98. handle *C.ALLEGRO_AUDIO_STREAM
  99. }
  100. type Mixer struct {
  101. handle *C.ALLEGRO_MIXER
  102. }
  103. type Voice struct {
  104. handle *C.ALLEGRO_VOICE
  105. }
  106. type AudioRecorder struct {
  107. handle *C.ALLEGRO_AUDIO_RECORDER
  108. }
  109. func (self *Sample) toC() *C.ALLEGRO_SAMPLE {
  110. return (*C.ALLEGRO_SAMPLE)(self.handle)
  111. }
  112. // Destroys the sample.
  113. func (self *Sample) Destroy() {
  114. if self.handle != nil {
  115. C.al_destroy_sample(self.toC())
  116. }
  117. self.handle = nil
  118. }
  119. // Sets up a finalizer for this Sample that calls Destroy() and return self
  120. func (self *Sample) SetDestroyFinalizer() *Sample {
  121. if self != nil {
  122. runtime.SetFinalizer(self, func(me *Sample) { me.Destroy() })
  123. }
  124. return self
  125. }
  126. func wrapSampleRaw(sample *C.ALLEGRO_SAMPLE) *Sample {
  127. if sample == nil {
  128. return nil
  129. }
  130. return &Sample{sample}
  131. }
  132. func wrapSample(sample *C.ALLEGRO_SAMPLE) *Sample {
  133. self := wrapSampleRaw(sample)
  134. if self != nil {
  135. runtime.SetFinalizer(self, func(me *Sample) { me.Destroy() })
  136. }
  137. return self
  138. }
  139. func createSample(data []byte, samples uint, freq uint, depth AudioDepth, chan_conf ChannelConf) *C.ALLEGRO_SAMPLE {
  140. // don't let allegro free the data, it's owned by Go.
  141. // XXX: copy data here in stead of using the go data???
  142. return C.al_create_sample(unsafe.Pointer(&data[0]), C.uint(samples),
  143. C.uint(freq), depth.toC(), chan_conf.toC(), b2cb(false))
  144. }
  145. // Creates a Sample with a Destroy finalizer set. BEWARE! data must be big enough fort he params
  146. // or this will crash spectacularly. Also, make sure that data doesn't get collected by the GC, or
  147. // trouble will arise.
  148. func CreateSample(data []byte, samples uint, freq uint, depth AudioDepth, chan_conf ChannelConf) *Sample {
  149. return wrapSample(createSample(data, samples, freq, depth, chan_conf))
  150. }
  151. // Returns the frequency of the sample
  152. func (self *Sample) Frequency() uint {
  153. return uint(C.al_get_sample_frequency(self.handle))
  154. }
  155. // Returns the length of the sample
  156. func (self *Sample) Length() uint {
  157. return uint(C.al_get_sample_length(self.handle))
  158. }
  159. // Returns the depth of the sample
  160. func (self *Sample) Depth() uint {
  161. return uint(C.al_get_sample_depth(self.handle))
  162. }
  163. // returns the amount of channels the sample has
  164. func (self *Sample) Channels() uint {
  165. return uint(C.al_get_sample_channels(self.handle))
  166. }
  167. // Returns the raw data pointer of the sample data.
  168. func (self *Sample) DataRaw() unsafe.Pointer {
  169. return (C.al_get_sample_data(self.handle))
  170. }
  171. // Returns the frequency of the sample instance
  172. func (self *SampleInstance) Frequency() uint {
  173. return uint(C.al_get_sample_instance_frequency(self.handle))
  174. }
  175. // Returns the length of the sample instance
  176. func (self *SampleInstance) Length() uint {
  177. return uint(C.al_get_sample_instance_length(self.handle))
  178. }
  179. // Returns the position of the sample instance
  180. func (self *SampleInstance) Position() uint {
  181. return uint(C.al_get_sample_instance_position(self.handle))
  182. }
  183. // Returns the of the sample instance
  184. func (self *SampleInstance) Speed() float32 {
  185. return float32(C.al_get_sample_instance_speed(self.handle))
  186. }
  187. // Returns the of the sample instance
  188. func (self *SampleInstance) Gain() float32 {
  189. return float32(C.al_get_sample_instance_gain(self.handle))
  190. }
  191. // Returns the of the sample instance
  192. func (self *SampleInstance) Pan() float32 {
  193. return float32(C.al_get_sample_instance_pan(self.handle))
  194. }
  195. // Returns the of the sample instance
  196. func (self *SampleInstance) Time() float32 {
  197. return float32(C.al_get_sample_instance_time(self.handle))
  198. }
  199. // Returns the depth of the sample instance
  200. func (self *SampleInstance) Depth() AudioDepth {
  201. return AudioDepth(C.al_get_sample_instance_depth(self.handle))
  202. }
  203. // Returns the channel configuration of the sample instance
  204. func (self *SampleInstance) Channels() ChannelConf {
  205. return ChannelConf(C.al_get_sample_instance_channels(self.handle))
  206. }
  207. // Returns the play mode of the sample instance
  208. func (self *SampleInstance) Playmode() PlayMode {
  209. return PlayMode(C.al_get_sample_instance_playmode(self.handle))
  210. }
  211. // Returns wheter or not the sample instance is playing
  212. func (self *SampleInstance) Playing() bool {
  213. return cb2b(C.al_get_sample_instance_playing(self.handle))
  214. }
  215. // Returns wheter or not the sample instance is attached
  216. func (self *SampleInstance) Attached() bool {
  217. return cb2b(C.al_get_sample_instance_attached(self.handle))
  218. }
  219. // Sets the position of the sample instance.
  220. func (self *SampleInstance) SetPosition(val uint) bool {
  221. return cb2b(C.al_set_sample_instance_position(self.handle, C.uint(val)))
  222. }
  223. // Sets the length of the sample instance.
  224. func (self *SampleInstance) SetLength(val uint) bool {
  225. return cb2b(C.al_set_sample_instance_length(self.handle, C.uint(val)))
  226. }
  227. // Sets the speed of the sample instance.
  228. func (self *SampleInstance) SetSpeed(val float32) bool {
  229. return cb2b(C.al_set_sample_instance_speed(self.handle, C.float(val)))
  230. }
  231. // Sets the gain of the sample instance.
  232. func (self *SampleInstance) SetGain(val float32) bool {
  233. return cb2b(C.al_set_sample_instance_gain(self.handle, C.float(val)))
  234. }
  235. // Sets the pan of the sample instance.
  236. func (self *SampleInstance) SetPan(val float32) bool {
  237. return cb2b(C.al_set_sample_instance_pan(self.handle, C.float(val)))
  238. }
  239. // Sets the play mode of the sample instance.
  240. func (self *SampleInstance) SetPlaymode(val PlayMode) bool {
  241. return cb2b(C.al_set_sample_instance_playmode(self.handle, val.toC()))
  242. }
  243. // Sets the play status of the sample instance.
  244. func (self *SampleInstance) SetPlaying(val bool) bool {
  245. return cb2b(C.al_set_sample_instance_playing(self.handle, b2cb(val)))
  246. }
  247. // Detaches the sample instance from it's player
  248. func (self *SampleInstance) Detach() bool {
  249. return cb2b(C.al_detach_sample_instance(self.handle))
  250. }
  251. // Sets the sample data to use for the sample instance
  252. func (self *SampleInstance) SetSample(val *Sample) bool {
  253. return cb2b(C.al_set_sample(self.handle, val.handle))
  254. }
  255. // Gets the RAW sample data that was linked to the sample instance
  256. func (self *SampleInstance) SampleRaw() *Sample {
  257. return wrapSampleRaw(C.al_get_sample(self.handle))
  258. }
  259. // Plays the sample instance
  260. func (self *SampleInstance) Play() bool {
  261. return cb2b(C.al_play_sample_instance(self.handle))
  262. }
  263. // Stops the sample instannce playback
  264. func (self *SampleInstance) Stop() bool {
  265. return cb2b(C.al_stop_sample_instance(self.handle))
  266. }
  267. func (self *AudioStream) toC() *C.ALLEGRO_AUDIO_STREAM {
  268. return (*C.ALLEGRO_AUDIO_STREAM)(self.handle)
  269. }
  270. // Destroys the audio stream.
  271. func (self *AudioStream) Destroy() {
  272. if self.handle != nil {
  273. C.al_destroy_audio_stream(self.toC())
  274. }
  275. self.handle = nil
  276. }
  277. // Sets up a finalizer for this AudioStream that calls Destroy() and return self
  278. func (self *AudioStream) SetDestroyFinalizer() *AudioStream {
  279. if self != nil {
  280. runtime.SetFinalizer(self, func(me *AudioStream) { me.Destroy() })
  281. }
  282. return self
  283. }
  284. func wrapAudioStreamRaw(data *C.ALLEGRO_AUDIO_STREAM) *AudioStream {
  285. if data == nil {
  286. return nil
  287. }
  288. return &AudioStream{data}
  289. }
  290. func wrapAudioStream(data *C.ALLEGRO_AUDIO_STREAM) *AudioStream {
  291. self := wrapAudioStreamRaw(data)
  292. return self.SetDestroyFinalizer()
  293. }
  294. // Creates an audio stream, with finalizer installed.
  295. func CreateAudioStream(bufc, samples, freq uint, depth AudioDepth, chan_conf ChannelConf) *AudioStream {
  296. return wrapAudioStream(C.al_create_audio_stream(C.size_t(bufc), C.uint(samples),
  297. C.uint(freq), depth.toC(), chan_conf.toC()))
  298. }
  299. // Creates an audio stream, with NO finalizer installed.
  300. func CreateAudioStreamRaw(bufc, samples, freq uint, depth AudioDepth, chan_conf ChannelConf) *AudioStream {
  301. return wrapAudioStreamRaw(C.al_create_audio_stream(C.size_t(bufc), C.uint(samples),
  302. C.uint(freq), depth.toC(), chan_conf.toC()))
  303. }
  304. // Drains all data from an audio stream
  305. func (self *AudioStream) Drain() {
  306. C.al_drain_audio_stream(self.handle)
  307. }
  308. // Returns the frequency of the audio stream
  309. func (self *AudioStream) Frequency() uint {
  310. return uint(C.al_get_audio_stream_frequency(self.handle))
  311. }
  312. // Returns the length of the audio stream
  313. func (self *AudioStream) Length() uint {
  314. return uint(C.al_get_audio_stream_length(self.handle))
  315. }
  316. // Returns the speed of the audio stream
  317. func (self *AudioStream) Speed() float32 {
  318. return float32(C.al_get_audio_stream_speed(self.handle))
  319. }
  320. // Returns the amount of fragments of the audio stream
  321. func (self *AudioStream) Fragments() float32 {
  322. return float32(C.al_get_audio_stream_fragments(self.handle))
  323. }
  324. // Returns the amount of available fragments of the audio stream
  325. func (self *AudioStream) AvailableFragments() float32 {
  326. return float32(C.al_get_available_audio_stream_fragments(self.handle))
  327. }
  328. // Returns the gain of the audio stream
  329. func (self *AudioStream) Gain() float32 {
  330. return float32(C.al_get_audio_stream_gain(self.handle))
  331. }
  332. // Returns the pan of the audio stream
  333. func (self *AudioStream) Pan() float32 {
  334. return float32(C.al_get_audio_stream_pan(self.handle))
  335. }
  336. // Returns the depth of the audio stream
  337. func (self *AudioStream) Depth() AudioDepth {
  338. return AudioDepth(C.al_get_audio_stream_depth(self.handle))
  339. }
  340. // Returns the channel configuration of the audio stream
  341. func (self *AudioStream) Channels() ChannelConf {
  342. return ChannelConf(C.al_get_audio_stream_channels(self.handle))
  343. }
  344. // Returns the play mode of the audio stream
  345. func (self *AudioStream) Playmode() PlayMode {
  346. return PlayMode(C.al_get_audio_stream_playmode(self.handle))
  347. }
  348. // Returns wheter or not the audio stream is playing
  349. func (self *AudioStream) Playing() bool {
  350. return cb2b(C.al_get_audio_stream_playing(self.handle))
  351. }
  352. // Returns wheter or not the audio stream is attached
  353. func (self *AudioStream) Attached() bool {
  354. return cb2b(C.al_get_audio_stream_attached(self.handle))
  355. }
  356. // Returns an unsafe pointer to the audio stream's fragment
  357. func (self *AudioStream) Fragment() unsafe.Pointer {
  358. return C.al_get_audio_stream_fragment(self.handle)
  359. }
  360. // Sets the speed of the audio stream.
  361. func (self *AudioStream) SetSpeed(val float32) bool {
  362. return cb2b(C.al_set_audio_stream_speed(self.handle, C.float(val)))
  363. }
  364. // Sets the gain of the audio stream.
  365. func (self *AudioStream) SetGain(val float32) bool {
  366. return cb2b(C.al_set_audio_stream_gain(self.handle, C.float(val)))
  367. }
  368. // Sets the pan of the audio stream.
  369. func (self *AudioStream) SetPan(val float32) bool {
  370. return cb2b(C.al_set_audio_stream_pan(self.handle, C.float(val)))
  371. }
  372. // Sets the play mode of the audio stream.
  373. func (self *AudioStream) SetPlaymode(val PlayMode) bool {
  374. return cb2b(C.al_set_audio_stream_playmode(self.handle, val.toC()))
  375. }
  376. // Sets the play status of the audio stream.
  377. func (self *AudioStream) SetPlaying(val bool) bool {
  378. return cb2b(C.al_set_audio_stream_playing(self.handle, b2cb(val)))
  379. }
  380. // Detaches the audio stream from it's player
  381. func (self *AudioStream) Detach() bool {
  382. return cb2b(C.al_detach_audio_stream(self.handle))
  383. }
  384. // Sets an unsafe pointer as the the audio stream's fragment
  385. func (self *AudioStream) SetFragment(ptr unsafe.Pointer) bool {
  386. return cb2b(C.al_set_audio_stream_fragment(self.handle, ptr))
  387. }
  388. // Rewinds the audio stream
  389. func (self *AudioStream) Rewind() bool {
  390. return cb2b(C.al_rewind_audio_stream(self.handle))
  391. }
  392. // Seeks to a position in the audio stream, expressed in seconds.
  393. func (self *AudioStream) SeekSeconds(secs float64) bool {
  394. return cb2b(C.al_seek_audio_stream_secs(self.handle, C.double(secs)))
  395. }
  396. // Gets the position in the audio stream, expressed in seconds.
  397. func (self *AudioStream) PositionSeconds() (secs float64) {
  398. return float64(C.al_get_audio_stream_position_secs(self.handle))
  399. }
  400. // Gets the length of the audio stream, expressed in seconds.
  401. func (self *AudioStream) LengthSeconds() (secs float64) {
  402. return float64(C.al_get_audio_stream_length_secs(self.handle))
  403. }
  404. // Sets up a loop in the audio stream, expressed in seconds.
  405. func (self *AudioStream) LoopSeconds(start, end float64) bool {
  406. return cb2b(C.al_set_audio_stream_loop_secs(self.handle, C.double(start), C.double(end)))
  407. }
  408. // Returns the event source to use to listen to events on the audio stream.
  409. func (self *AudioStream) Eventsource() *EventSource {
  410. return wrapEventSourceRaw(C.al_get_audio_stream_event_source(self.handle))
  411. }
  412. // Converts a mixer to it's underlying C pointer
  413. func (self *Mixer) toC() *C.ALLEGRO_MIXER {
  414. return (*C.ALLEGRO_MIXER)(self.handle)
  415. }
  416. // Destroys the mixer.
  417. func (self *Mixer) Destroy() {
  418. if self.handle != nil {
  419. C.al_destroy_mixer(self.toC())
  420. }
  421. self.handle = nil
  422. }
  423. // Sets up a finalizer for this Mixer that calls Destroy() and return self
  424. func (self *Mixer) SetDestroyFinalizer() *Mixer {
  425. if self != nil {
  426. runtime.SetFinalizer(self, func(me *Mixer) { me.Destroy() })
  427. }
  428. return self
  429. }
  430. // Wraps a C mixer into a go mixer
  431. func wrapMixerRaw(data *C.ALLEGRO_MIXER) *Mixer {
  432. if data == nil {
  433. return nil
  434. }
  435. return &Mixer{data}
  436. }
  437. // Wraps a C mixer into a go mixer and sets up a finalizer that calls Destroy()
  438. func wrapMixer(data *C.ALLEGRO_MIXER) *Mixer {
  439. self := wrapMixerRaw(data)
  440. return self.SetDestroyFinalizer()
  441. }
  442. func createMixer(freq uint, depth AudioDepth, chan_conf ChannelConf) *C.ALLEGRO_MIXER {
  443. return C.al_create_mixer(C.uint(freq), depth.toC(), chan_conf.toC())
  444. }
  445. // Creates a new mixer with no finaliser attached to it.
  446. func CreateMixerRaw(freq uint, depth AudioDepth, chan_conf ChannelConf) *Mixer {
  447. return wrapMixerRaw(createMixer(freq, depth, chan_conf))
  448. }
  449. // Creates a new mixer with a finaliser that will call Destroy attached to it.
  450. func CreateMixer(freq uint, depth AudioDepth, chan_conf ChannelConf) *Mixer {
  451. return wrapMixer(createMixer(freq, depth, chan_conf))
  452. }
  453. // Attaches a sample instance to the given mixer.
  454. func (mixer *Mixer) AttachSampleInstance(stream *SampleInstance) bool {
  455. return cb2b(C.al_attach_sample_instance_to_mixer(stream.handle, mixer.handle))
  456. }
  457. // Attaches the sample instance to the given mixer.
  458. func (stream *SampleInstance) Attach(mixer *Mixer) bool {
  459. return cb2b(C.al_attach_sample_instance_to_mixer(stream.handle, mixer.handle))
  460. }
  461. // Attaches an audio stream to the given mixer.
  462. func (mixer *Mixer) AttachAudioStream(stream *AudioStream) bool {
  463. return cb2b(C.al_attach_audio_stream_to_mixer(stream.handle, mixer.handle))
  464. }
  465. // Attaches the audio stream to the given mixer.
  466. func (stream *AudioStream) Attach(mixer *Mixer) bool {
  467. return cb2b(C.al_attach_audio_stream_to_mixer(stream.handle, mixer.handle))
  468. }
  469. // Attaches a mixer to the given mixer.
  470. func (mixer *Mixer) AttachMixer(stream *Mixer) bool {
  471. return cb2b(C.al_attach_mixer_to_mixer(stream.handle, mixer.handle))
  472. }
  473. // Attaches the given mixer to the latter mixer.
  474. func (stream *Mixer) Attach(mixer *Mixer) bool {
  475. return cb2b(C.al_attach_mixer_to_mixer(stream.handle, mixer.handle))
  476. }
  477. /*
  478. TODO:
  479. ALLEGRO_KCM_AUDIO_FUNC(bool, al_set_mixer_postprocess_callback, (
  480. ALLEGRO_MIXER *mixer,
  481. void (*cb)(void *buf, unsigned int samples, void *data),
  482. void *data));
  483. */
  484. // Returns the frequency of the mixer
  485. func (self *Mixer) Frequency() uint {
  486. return uint(C.al_get_mixer_frequency(self.handle))
  487. }
  488. // Returns the gain of the mixer
  489. func (self *Mixer) Gain() float32 {
  490. return float32(C.al_get_mixer_gain(self.handle))
  491. }
  492. // Returns the depth of the mixer
  493. func (self *Mixer) Depth() AudioDepth {
  494. return AudioDepth(C.al_get_mixer_depth(self.handle))
  495. }
  496. // Returns the channel configuration of the mixer
  497. func (self *Mixer) Channels() ChannelConf {
  498. return ChannelConf(C.al_get_mixer_channels(self.handle))
  499. }
  500. // Returns the quality of the mixer
  501. func (self *Mixer) Quality() MixerQuality {
  502. return MixerQuality(C.al_get_mixer_quality(self.handle))
  503. }
  504. // Returns wheter or not the mixer is playing
  505. func (self *Mixer) Playing() bool {
  506. return cb2b(C.al_get_mixer_playing(self.handle))
  507. }
  508. // Returns wheter or not the mixer is attached
  509. func (self *Mixer) Attached() bool {
  510. return cb2b(C.al_get_mixer_attached(self.handle))
  511. }
  512. // Sets the frequency of the mixer.
  513. func (self *Mixer) SetFrequency(val uint) bool {
  514. return cb2b(C.al_set_mixer_frequency(self.handle, C.uint(val)))
  515. }
  516. // Sets the quality of the mixer.
  517. func (self *Mixer) SetQuality(val MixerQuality) bool {
  518. return cb2b(C.al_set_mixer_quality(self.handle, val.toC()))
  519. }
  520. // Sets the gain of the mixer.
  521. func (self *Mixer) SetGain(val float32) bool {
  522. return cb2b(C.al_set_mixer_gain(self.handle, C.float(val)))
  523. }
  524. // Sets the play status of the mixer.
  525. func (self *Mixer) SetPlaying(val bool) bool {
  526. return cb2b(C.al_set_mixer_playing(self.handle, b2cb(val)))
  527. }
  528. // Detaches the mixer from it's player
  529. func (self *Mixer) Detach() bool {
  530. return cb2b(C.al_detach_mixer(self.handle))
  531. }
  532. // Converts a voice to it's underlying C pointer
  533. func (self *Voice) toC() *C.ALLEGRO_VOICE {
  534. return (*C.ALLEGRO_VOICE)(self.handle)
  535. }
  536. // Destroys the voice.
  537. func (self *Voice) Destroy() {
  538. if self.handle != nil {
  539. C.al_destroy_voice(self.toC())
  540. }
  541. self.handle = nil
  542. }
  543. // Wraps a C voice into a go mixer
  544. func wrapVoiceRaw(data *C.ALLEGRO_VOICE) *Voice {
  545. if data == nil {
  546. return nil
  547. }
  548. return &Voice{data}
  549. }
  550. // Sets up a finalizer for this Voice Wraps a C voice that calls Destroy()
  551. func (self *Voice) SetDestroyFinalizer() *Voice {
  552. if self != nil {
  553. runtime.SetFinalizer(self, func(me *Voice) { me.Destroy() })
  554. }
  555. return self
  556. }
  557. // Wraps a C voice into a go mixer and sets up a finalizer that calls Destroy()
  558. func wrapVoice(data *C.ALLEGRO_VOICE) *Voice {
  559. self := wrapVoiceRaw(data)
  560. return self.SetDestroyFinalizer()
  561. }
  562. // creates a C voice
  563. func createVoice(freq uint, depth AudioDepth, chan_conf ChannelConf) *C.ALLEGRO_VOICE {
  564. return C.al_create_voice(C.uint(freq), depth.toC(), chan_conf.toC())
  565. }
  566. // Creates a voice
  567. func CreateVoiceRaw(freq uint, depth AudioDepth, chan_conf ChannelConf) *Voice {
  568. return wrapVoiceRaw(createVoice(freq, depth, chan_conf))
  569. }
  570. // Creates a voice and setsup a finalizer on it that calls Destroy
  571. func CreateVoice(freq uint, depth AudioDepth, chan_conf ChannelConf) *Voice {
  572. return wrapVoice(createVoice(freq, depth, chan_conf))
  573. }
  574. // Attaches a sample instance to the given voice.
  575. func (voice *Voice) AttachSampleInstance(stream *SampleInstance) bool {
  576. return cb2b(C.al_attach_sample_instance_to_voice(stream.handle, voice.handle))
  577. }
  578. // Attaches the sample instance to the given voice.
  579. func (stream *SampleInstance) AttachToVoice(voice *Voice) bool {
  580. return cb2b(C.al_attach_sample_instance_to_voice(stream.handle, voice.handle))
  581. }
  582. // Attaches an audio stream to the given voice.
  583. func (voice *Voice) AttachAudioStream(stream *AudioStream) bool {
  584. return cb2b(C.al_attach_audio_stream_to_voice(stream.handle, voice.handle))
  585. }
  586. // Attaches the audio stream to the given voice.
  587. func (stream *AudioStream) AttachToVoice(voice *Voice) bool {
  588. return cb2b(C.al_attach_audio_stream_to_voice(stream.handle, voice.handle))
  589. }
  590. // Attaches the given mixer to the voice.
  591. func (mixer *Mixer) AttachToVoice(voice *Voice) bool {
  592. return cb2b(C.al_attach_mixer_to_voice(mixer.handle, voice.handle))
  593. }
  594. // Attaches the given voice to the mixer.
  595. func (voice *Voice) AttachMixer(mixer *Mixer) bool {
  596. return cb2b(C.al_attach_mixer_to_voice(mixer.handle, voice.handle))
  597. }
  598. // Detaches the voice.
  599. func (voice *Voice) Detach() {
  600. C.al_detach_voice(voice.handle)
  601. }
  602. // Returns the frequency of the voice
  603. func (self *Voice) Frequency() uint {
  604. return uint(C.al_get_voice_frequency(self.handle))
  605. }
  606. // Returns the position of the voice
  607. func (self *Voice) Position() uint {
  608. return uint(C.al_get_voice_position(self.handle))
  609. }
  610. // Returns the depth of the voice
  611. func (self *Voice) Depth() AudioDepth {
  612. return AudioDepth(C.al_get_voice_depth(self.handle))
  613. }
  614. // Returns the channel configuration of the voice
  615. func (self *Voice) Channels() ChannelConf {
  616. return ChannelConf(C.al_get_voice_channels(self.handle))
  617. }
  618. // Returns wheter or not the voice is playing
  619. func (self *Voice) Playing() bool {
  620. return cb2b(C.al_get_voice_playing(self.handle))
  621. }
  622. // Sets the position of the voice.
  623. func (self *Voice) SetPosition(val uint) bool {
  624. return cb2b(C.al_set_voice_position(self.handle, C.uint(val)))
  625. }
  626. // Sets the play status of the voice.
  627. func (self *Voice) SetPlaying(val bool) bool {
  628. return cb2b(C.al_set_voice_playing(self.handle, b2cb(val)))
  629. }
  630. // Installs the audio extension
  631. func InstallAudio() bool {
  632. return cb2b(C.al_install_audio())
  633. }
  634. // Uninstalls the audio extension
  635. func UninstallAudio() {
  636. C.al_uninstall_audio()
  637. }
  638. // Returns true if the audio extension is installed
  639. func IsAudioInstalled() bool {
  640. return cb2b(C.al_is_audio_installed())
  641. }
  642. // Returns the version of the audio extension
  643. func AudioVersion() uint32 {
  644. return uint32(C.al_get_allegro_audio_version())
  645. }
  646. // Gets the amount of available channels in a channel configguration
  647. func (self ChannelConf) ChannelCount() uint {
  648. return uint(C.al_get_channel_count(self.toC()))
  649. }
  650. // Gets the size of (foe calculating the size of allocating a sample)
  651. func (self AudioDepth) Size() uint {
  652. return uint(C.al_get_audio_depth_size(self.toC()))
  653. }
  654. // Reserves the given amount of samples and attaches them to the default mixer
  655. func ReserveSamples(samples int) bool {
  656. return cb2b(C.al_reserve_samples(C.int(samples)))
  657. }
  658. var defaultMixer *Mixer = nil
  659. // Returns a pointer to the default mixer. Has no dispose finaliser set.
  660. func DefaultMixer() *Mixer {
  661. return wrapMixerRaw(C.al_get_default_mixer())
  662. }
  663. // Sets the mixer as the default mixer.
  664. func (mixer *Mixer) SetDefault() {
  665. // this is purely to prevent the GC from collecting this mixer.
  666. defaultMixer = mixer
  667. C.al_set_default_mixer(mixer.handle)
  668. }
  669. // Restores the default mixer
  670. func RestoreDefaultMixer() {
  671. // GC reclaim is OK now.
  672. defaultMixer = nil
  673. C.al_restore_default_mixer()
  674. }
  675. // Plays a sample on the default mixer if enough samples have been reserved.
  676. // id returns a sample if that can be used to track the sample.
  677. func (self *Sample) Play(gain, pan, speed float32, loop PlayMode) (ok bool, id SampleId) {
  678. ok = cb2b(C.al_play_sample(self.handle, C.float(gain), C.float(pan), C.float(speed), loop.toC(), (&id).toC()))
  679. return ok, id
  680. }
  681. // Stops playing a sample that was started with sample.Play()
  682. func (self *SampleId) Stop() {
  683. C.al_stop_sample(self.toC())
  684. }
  685. // Stops playing all samples on the default mixer
  686. func StopSamples() {
  687. C.al_stop_samples()
  688. }
  689. /*
  690. Todo:
  691. ALLEGRO_KCM_AUDIO_FUNC(bool, al_register_sample_loader, (const char *ext,
  692. ALLEGRO_SAMPLE *(*loader)(const char *filename)));
  693. ALLEGRO_KCM_AUDIO_FUNC(bool, al_register_sample_saver, (const char *ext,
  694. bool (*saver)(const char *filename, ALLEGRO_SAMPLE *spl)));
  695. ALLEGRO_KCM_AUDIO_FUNC(bool, al_register_audio_stream_loader, (const char *ext,
  696. ALLEGRO_AUDIO_STREAM *(*stream_loader)(const char *filename,
  697. size_t buffer_count, unsigned int samples)));
  698. ALLEGRO_KCM_AUDIO_FUNC(bool, al_register_sample_loader_f, (const char *ext,
  699. ALLEGRO_SAMPLE *(*loader)(ALLEGRO_FILE *fp)));
  700. ALLEGRO_KCM_AUDIO_FUNC(bool, al_register_sample_saver_f, (const char *ext,
  701. bool (*saver)(ALLEGRO_FILE *fp, ALLEGRO_SAMPLE *spl)));
  702. ALLEGRO_KCM_AUDIO_FUNC(bool, al_register_audio_stream_loader_f, (const char *ext,
  703. ALLEGRO_AUDIO_STREAM *(*stream_loader)(ALLEGRO_FILE *fp,
  704. size_t buffer_count, unsigned int samples)));
  705. */
  706. // Loads a C sample from a filename
  707. func loadSample(filename string) *C.ALLEGRO_SAMPLE {
  708. cstr := cstr(filename)
  709. defer cstrFree(cstr)
  710. return C.al_load_sample(cstr)
  711. }
  712. // Loads a sample from a filename and sets up no finalizer
  713. func LoadSampleRaw(filename string) *Sample {
  714. return wrapSampleRaw(loadSample(filename))
  715. }
  716. // Loads a sample from a filename and sets up a finalizer
  717. func LoadSample(filename string) *Sample {
  718. return LoadSampleRaw(filename).SetDestroyFinalizer()
  719. }
  720. // Saves a sample to a given filename
  721. func (self *Sample) Save(filename string) bool {
  722. cstr := cstr(filename)
  723. defer cstrFree(cstr)
  724. return cb2b(C.al_save_sample(cstr, self.handle))
  725. }
  726. // Loads a C audio stream sample from a filename
  727. func loadAudioStream(filename string, buffer_count, samples uint) *C.ALLEGRO_AUDIO_STREAM {
  728. cstr := cstr(filename)
  729. defer cstrFree(cstr)
  730. return C.al_load_audio_stream(cstr, C.size_t(buffer_count), C.uint(samples))
  731. }
  732. // Loads a sample from a filename and sets up no finalizer
  733. func LoadAudioStreamRaw(filename string, buffer_count, samples uint) *AudioStream {
  734. return wrapAudioStreamRaw(loadAudioStream(filename, buffer_count, samples))
  735. }
  736. // Loads a sample from a filename and sets up a finalizer
  737. func LoadAudioStream(filename string, buffer_count, samples uint) *AudioStream {
  738. return LoadAudioStreamRaw(filename, buffer_count, samples).SetDestroyFinalizer()
  739. }
  740. // Allegro's own file for cross platform and physfs reasons.
  741. type File struct {
  742. handle *C.ALLEGRO_FILE
  743. }
  744. // Closes the Allegro file
  745. func (self *File) Close() {
  746. if self.handle != nil {
  747. C.al_fclose(self.handle)
  748. }
  749. self.handle = nil
  750. }
  751. // Wraps an ALLEGRO_FILE into a File
  752. func wrapFileRaw(file *C.ALLEGRO_FILE) *File {
  753. if file == nil {
  754. return nil
  755. }
  756. return &File{file}
  757. }
  758. // Opens an Allegro File
  759. func openFile(filename, mode string) *C.ALLEGRO_FILE {
  760. cfilename := cstr(filename)
  761. defer cstrFree(cfilename)
  762. cmode := cstr(mode)
  763. defer cstrFree(cmode)
  764. return C.al_fopen(cfilename, cmode)
  765. }
  766. // Sets up a finalizer for this File that calls Close()
  767. func (self *File) SetCloseFinalizer() *File {
  768. if self != nil {
  769. runtime.SetFinalizer(self, func(me *File) { me.Close() })
  770. }
  771. return self
  772. }
  773. // Wraps a file and sets up a finalizer that calls Destroy()
  774. func wrapFile(data *C.ALLEGRO_FILE) *File {
  775. self := wrapFileRaw(data)
  776. return self.SetCloseFinalizer()
  777. }
  778. // Opens a file with no finalizer set
  779. func OpenFileRaw(filename, mode string) *File {
  780. self := openFile(filename, mode)
  781. return wrapFileRaw(self)
  782. }
  783. // Opens a file with a Close finalizer set
  784. func OpenFile(filename, mode string) *File {
  785. self := OpenFileRaw(filename, mode)
  786. return self.SetCloseFinalizer()
  787. }
  788. // Loads a Sample from a File. Filetype is a file extension that identifies the file type
  789. // like (.wav, .ogg, etc))
  790. func (self *File) loadSample(filetype string) *C.ALLEGRO_SAMPLE {
  791. cfiletype := cstr(filetype)
  792. defer cstrFree(cfiletype)
  793. return C.al_load_sample_f(self.handle, cfiletype)
  794. }
  795. // Saves a Sample to a File. Filetype is a file extension that identifies the file type
  796. func (self *File) SaveSample(filetype string, sample *Sample) bool {
  797. cfiletype := cstr(filetype)
  798. defer cstrFree(cfiletype)
  799. return cb2b(C.al_save_sample_f(self.handle, cfiletype, sample.handle))
  800. }
  801. // Loads an ALLEGRO_AUDIO_STREAM from a file. Filetype is a file extension
  802. // that identifies the file type (.ogg, etc)
  803. func (self *File) loadAudioStream(filetype string, buffer_count,
  804. samples uint) *C.ALLEGRO_AUDIO_STREAM {
  805. cfiletype := cstr(filetype)
  806. defer cstrFree(cfiletype)
  807. return C.al_load_audio_stream_f(self.handle, cfiletype,
  808. C.size_t(buffer_count), C.uint(samples))
  809. }
  810. // Loads a Sample from a File. Filetype is a file extension that identifies the file type
  811. // like (.wav, .ogg, etc))
  812. func (self *File) LoadSampleRaw(filetype string) *Sample {
  813. return wrapSampleRaw(loadSample(filetype))
  814. }
  815. // Loads a Sample from a File. Filetype is a file extension that identifies the file type
  816. // like (.wav, .ogg, etc)). Sets up a finalizer.
  817. func (self *File) LoadSample(filetype string) *Sample {
  818. return LoadSampleRaw(filetype).SetDestroyFinalizer()
  819. }
  820. // Loads an AudioStream from a file. Filetype is a file extension
  821. // that identifies the file type (.ogg, etc)
  822. func (self *File) LoadAudioStreamRaw(filetype string, buffer_count,
  823. samples uint) *AudioStream {
  824. return wrapAudioStreamRaw(loadAudioStream(filetype, buffer_count, samples))
  825. }
  826. // Loads an AudioStream from a file. Filetype is a file extension
  827. // that identifies the file type (.ogg, etc). Sets up a finalizer.
  828. func (self *File) LoadAudioStream(filetype string, buffer_count,
  829. samples uint) *AudioStream {
  830. return LoadAudioStreamRaw(filetype, buffer_count, samples).SetDestroyFinalizer()
  831. }
  832. // Converts a recorder to it's underlying C pointer
  833. func (self *AudioRecorder) toC() *C.ALLEGRO_AUDIO_RECORDER {
  834. return (*C.ALLEGRO_AUDIO_RECORDER)(self.handle)
  835. }
  836. // Destroys the recorder.
  837. func (self *AudioRecorder) Destroy() {
  838. if self.handle != nil {
  839. C.al_destroy_audio_recorder(self.toC())
  840. }
  841. self.handle = nil
  842. }
  843. // Wraps a C recorder into a go mixer
  844. func wrapAudioRecorderRaw(data *C.ALLEGRO_AUDIO_RECORDER) *AudioRecorder {
  845. if data == nil {
  846. return nil
  847. }
  848. return &AudioRecorder{data}
  849. }
  850. // Sets up a finalizer for this AudioRecorder Wraps a C recorder that calls Destroy()
  851. func (self *AudioRecorder) SetDestroyFinalizer() *AudioRecorder {
  852. if self != nil {
  853. runtime.SetFinalizer(self, func(me *AudioRecorder) { me.Destroy() })
  854. }
  855. return self
  856. }
  857. // Wraps a C recorder into a go recorder and sets up a finalizer that calls Destroy()
  858. func wrapAudioRecorder(data *C.ALLEGRO_AUDIO_RECORDER) *AudioRecorder {
  859. self := wrapAudioRecorderRaw(data)
  860. return self.SetDestroyFinalizer()
  861. }
  862. // Creates a C recorder
  863. func createAudioRecorder(fragment_count, samples, freq uint,
  864. depth AudioDepth, chan_conf ChannelConf) *C.ALLEGRO_AUDIO_RECORDER {
  865. return C.al_create_audio_recorder(C.size_t(fragment_count), C.uint(samples),
  866. C.uint(freq), depth.toC(), chan_conf.toC())
  867. }
  868. // Creates an Audio Recorder and sets no finalizer
  869. func CreateAudioRecorderRaw(fragment_count, samples, freq uint,
  870. depth AudioDepth, chan_conf ChannelConf) *AudioRecorder {
  871. return wrapAudioRecorderRaw(createAudioRecorder(fragment_count, samples, freq, depth, chan_conf))
  872. }
  873. // Creates an Audio Recorder and sets a finalizer
  874. func CreateAudioRecorder(fragment_count, samples, freq uint,
  875. depth AudioDepth, chan_conf ChannelConf) *AudioRecorder {
  876. return CreateAudioRecorderRaw(fragment_count, samples,
  877. freq, depth, chan_conf).SetDestroyFinalizer()
  878. }
  879. // Starts recording on the audio recorder.
  880. func (self *AudioRecorder) Start() bool {
  881. return cb2b(C.al_start_audio_recorder(self.handle))
  882. }
  883. // Stops recording on the audio recorder.
  884. func (self *AudioRecorder) Stop() {
  885. C.al_stop_audio_recorder(self.handle)
  886. }
  887. // Gets the audio recorder's event source
  888. func (self *AudioRecorder) EventSource() *EventSource {
  889. return wrapEventSourceRaw(C.al_get_audio_recorder_event_source(self.handle))
  890. }
  891. // Converts to AudioRecorderEvent
  892. func wrapAudioRecorderEvent(event *C.ALLEGRO_AUDIO_RECORDER_EVENT) *AudioRecorderEvent {
  893. return (*AudioRecorderEvent)(event)
  894. }
  895. // Converts an event into an allegro recorder event
  896. func (self *Event) AudioRecorderEvent() *AudioRecorderEvent {
  897. return wrapAudioRecorderEvent(C.al_get_audio_recorder_event(self.toC()))
  898. }
  899. // Gets an unsafe pointer to the recorder event's buffer
  900. func (self *AudioRecorderEvent) BufferPointer() unsafe.Pointer {
  901. return self.buffer
  902. }
  903. // Gets the amount of samples for this recorder event
  904. func (self *AudioRecorderEvent) Samples() uint {
  905. return uint(self.samples)
  906. }
  907. // Gets the recorder's buffer copied into a byte slice
  908. func (self *AudioRecorderEvent) Buffer() []byte {
  909. return C.GoBytes(self.buffer, C.int(self.samples))
  910. }