audio.lua 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. -- love.audio
  2. --------------------------------------------------------------------------------
  3. --------------------------------------------------------------------------------
  4. ------------------------------------OBJECTS-------------------------------------
  5. --------------------------------------------------------------------------------
  6. --------------------------------------------------------------------------------
  7. -- RecordingDevice (love.audio.getRecordingDevices)
  8. love.test.audio.RecordingDevice = function(test)
  9. -- skip recording device on runners, they cant emulate it
  10. if GITHUB_RUNNER == true then
  11. return test:skipTest('cant emulate recording devices in CI')
  12. end
  13. -- check devices first
  14. local devices = love.audio.getRecordingDevices()
  15. if #devices == 0 then
  16. return test:skipTest('cant test this works: no recording devices found')
  17. end
  18. -- check object created and basics
  19. local device = devices[1]
  20. test:assertObject(device)
  21. test:assertMatch({1, 2}, device:getChannelCount(), 'check channel count is 1 or 2')
  22. test:assertNotEquals(nil, device:getName(), 'check has name')
  23. -- check initial data is empty as we haven't recorded anything yet
  24. test:assertNotNil(device:getBitDepth())
  25. test:assertEquals(nil, device:getData(), 'check initial data empty')
  26. test:assertEquals(0, device:getSampleCount(), 'check initial sample empty')
  27. test:assertNotNil(device:getSampleRate())
  28. test:assertFalse(device:isRecording(), 'check not recording')
  29. -- start recording for a short time
  30. local startrecording = device:start(32000, 4000, 16, 1)
  31. test:waitFrames(10)
  32. test:assertTrue(startrecording, 'check recording started')
  33. test:assertTrue(device:isRecording(), 'check now recording')
  34. test:assertEquals(4000, device:getSampleRate(), 'check sample rate set')
  35. test:assertEquals(16, device:getBitDepth(), 'check bit depth set')
  36. test:assertEquals(1, device:getChannelCount(), 'check channel count set')
  37. local recording = device:stop()
  38. test:waitFrames(10)
  39. -- after recording
  40. test:assertFalse(device:isRecording(), 'check not recording')
  41. test:assertEquals(nil, device:getData(), 'using stop should clear buffer')
  42. test:assertObject(recording)
  43. end
  44. -- Source (love.audio.newSource)
  45. love.test.audio.Source = function(test)
  46. -- create stereo source
  47. local stereo = love.audio.newSource('resources/click.ogg', 'static')
  48. test:assertObject(stereo)
  49. -- check stereo props
  50. test:assertEquals(2, stereo:getChannelCount(), 'check stereo src')
  51. test:assertRange(stereo:getDuration("seconds"), 0, 0.1, 'check stereo seconds')
  52. test:assertNotNil(stereo:getFreeBufferCount())
  53. test:assertEquals('static', stereo:getType(), 'check stereo type')
  54. -- check cloning a stereo
  55. local clone = stereo:clone()
  56. test:assertEquals(2, clone:getChannelCount(), 'check clone stereo src')
  57. test:assertRange(clone:getDuration("seconds"), 0, 0.1, 'check clone stereo seconds')
  58. test:assertNotNil(clone:getFreeBufferCount())
  59. test:assertEquals('static', clone:getType(), 'check cloned stereo type')
  60. -- mess with stereo playing
  61. test:assertFalse(stereo:isPlaying(), 'check not playing')
  62. stereo:setLooping(true)
  63. stereo:play()
  64. test:assertTrue(stereo:isPlaying(), 'check now playing')
  65. test:assertTrue(stereo:isLooping(), 'check now playing')
  66. stereo:pause()
  67. stereo:seek(0.01, 'seconds')
  68. test:assertEquals(0.01, stereo:tell('seconds'), 'check seek/tell')
  69. stereo:stop()
  70. test:assertFalse(stereo:isPlaying(), 'check stopped playing')
  71. -- check volume limits
  72. stereo:setVolumeLimits(0.1, 0.5)
  73. local min, max = stereo:getVolumeLimits()
  74. test:assertRange(min, 0.1, 0.2, 'check min limit')
  75. test:assertRange(max, 0.5, 0.6, 'check max limit')
  76. -- check setting volume
  77. stereo:setVolume(1)
  78. test:assertEquals(1, stereo:getVolume(), 'check set volume')
  79. stereo:setVolume(0)
  80. test:assertEquals(0, stereo:getVolume(), 'check set volume')
  81. -- change some get/set props that can apply to stereo
  82. stereo:setPitch(2)
  83. test:assertEquals(2, stereo:getPitch(), 'check pitch change')
  84. -- create mono source
  85. local mono = love.audio.newSource('resources/clickmono.ogg', 'stream')
  86. test:assertObject(mono)
  87. test:assertEquals(1, mono:getChannelCount(), 'check mono src')
  88. test:assertEquals(2927, mono:getDuration("samples"), 'check mono seconds')
  89. test:assertEquals('stream', mono:getType(), 'check mono type')
  90. -- air absorption
  91. test:assertEquals(0, mono:getAirAbsorption(), 'get air absorption')
  92. mono:setAirAbsorption(1)
  93. test:assertEquals(1, mono:getAirAbsorption(), 'set air absorption')
  94. -- cone
  95. mono:setCone(0, 90*(math.pi/180), 1)
  96. local ia, oa, ov = mono:getCone()
  97. test:assertEquals(0, ia, 'check cone ia')
  98. test:assertEquals(math.floor(9000*(math.pi/180)), math.floor(oa*100), 'check cone oa')
  99. test:assertEquals(1, ov, 'check cone ov')
  100. -- direction
  101. mono:setDirection(3, 1, -1)
  102. local x, y, z = mono:getDirection()
  103. test:assertEquals(3, x, 'check direction x')
  104. test:assertEquals(1, y, 'check direction y')
  105. test:assertEquals(-1, z, 'check direction z')
  106. -- relative
  107. mono:setRelative(true)
  108. test:assertTrue(mono:isRelative(), 'check set relative')
  109. -- position
  110. mono:setPosition(1, 2, 3)
  111. x, y, z = mono:getPosition()
  112. test:assertEquals(x, 1, 'check pos x')
  113. test:assertEquals(y, 2, 'check pos y')
  114. test:assertEquals(z, 3, 'check pos z')
  115. -- velocity
  116. mono:setVelocity(1, 3, 4)
  117. x, y, z = mono:getVelocity()
  118. test:assertEquals(x, 1, 'check velocity x')
  119. test:assertEquals(y, 3, 'check velocity x')
  120. test:assertEquals(z, 4, 'check velocity x')
  121. -- rolloff
  122. mono:setRolloff(1)
  123. test:assertEquals(1, mono:getRolloff(), 'check rolloff set')
  124. -- create queue source
  125. local queue = love.audio.newQueueableSource(44100, 16, 1, 3)
  126. local sdata = love.sound.newSoundData(1024, 44100, 16, 1)
  127. test:assertObject(queue)
  128. local run = queue:queue(sdata)
  129. test:assertTrue(run, 'check queued sound')
  130. queue:stop()
  131. -- check making a filer
  132. local setfilter = stereo:setFilter({
  133. type = 'lowpass',
  134. volume = 0.5,
  135. highgain = 0.3
  136. })
  137. test:assertTrue(setfilter, 'check filter applied')
  138. local filter = stereo:getFilter()
  139. test:assertEquals('lowpass', filter.type, 'check filter type')
  140. test:assertEquals(0.5, filter.volume, 'check filter volume')
  141. test:assertRange(filter.highgain, 0.3, 0.4, 'check filter highgain')
  142. test:assertEquals(nil, filter.lowgain, 'check filter lowgain')
  143. -- add an effect
  144. local effsource = love.audio.newSource('resources/click.ogg', 'static')
  145. love.audio.setEffect('testeffect', {
  146. type = 'flanger',
  147. volume = 10
  148. })
  149. local seteffect, err = effsource:setEffect('testeffect', {
  150. type = 'highpass',
  151. volume = 0.3,
  152. lowgain = 0.1
  153. })
  154. -- both these fail on 12 using stereo or mono, no err
  155. test:assertTrue(seteffect, 'check effect was applied')
  156. local filtersettings = effsource:getEffect('effectthatdoesntexist', {})
  157. test:assertNotNil(filtersettings)
  158. end
  159. --------------------------------------------------------------------------------
  160. --------------------------------------------------------------------------------
  161. ------------------------------------METHODS-------------------------------------
  162. --------------------------------------------------------------------------------
  163. --------------------------------------------------------------------------------
  164. -- love.audio.getActiveEffects
  165. love.test.audio.getActiveEffects = function(test)
  166. -- check we get a value
  167. test:assertNotNil(love.audio.getActiveEffects())
  168. -- check setting an effect active
  169. love.audio.setEffect('testeffect', {
  170. type = 'chorus',
  171. volume = 10
  172. })
  173. test:assertEquals(1, #love.audio.getActiveEffects(), 'check 1 effect running')
  174. test:assertEquals('testeffect', love.audio.getActiveEffects()[1], 'check effect details')
  175. end
  176. -- love.audio.getActiveSourceCount
  177. love.test.audio.getActiveSourceCount = function(test)
  178. -- check we get a value
  179. test:assertNotNil(love.audio.getActiveSourceCount())
  180. -- check source isn't active by default
  181. local testsource = love.audio.newSource('resources/click.ogg', 'static')
  182. test:assertEquals(0, love.audio.getActiveSourceCount(), 'check not active')
  183. -- check playing a source marks it as active
  184. love.audio.play(testsource)
  185. test:assertEquals(1, love.audio.getActiveSourceCount(), 'check now active')
  186. love.audio.pause()
  187. end
  188. -- love.audio.getDistanceModel
  189. love.test.audio.getDistanceModel = function(test)
  190. -- check we get a value
  191. test:assertNotNil(love.audio.getDistanceModel())
  192. -- check default value from documentation
  193. test:assertEquals('inverseclamped', love.audio.getDistanceModel(), 'check default value')
  194. -- check get correct value after setting
  195. love.audio.setDistanceModel('inverse')
  196. test:assertEquals('inverse', love.audio.getDistanceModel(), 'check setting model')
  197. end
  198. -- love.audio.getDopplerScale
  199. love.test.audio.getDopplerScale = function(test)
  200. -- check default value
  201. test:assertEquals(1, love.audio.getDopplerScale(), 'check default 1')
  202. -- check correct value after setting to 0
  203. love.audio.setDopplerScale(0)
  204. test:assertEquals(0, love.audio.getDopplerScale(), 'check setting to 0')
  205. love.audio.setDopplerScale(1)
  206. end
  207. -- love.audio.getEffect
  208. love.test.audio.getEffect = function(test)
  209. -- check getting a non-existent effect
  210. test:assertEquals(nil, love.audio.getEffect('madeupname'), 'check wrong name')
  211. -- check getting a valid effect
  212. love.audio.setEffect('testeffect', {
  213. type = 'chorus',
  214. volume = 10
  215. })
  216. test:assertNotNil(love.audio.getEffect('testeffect'))
  217. -- check effect values match creation values
  218. test:assertEquals('chorus', love.audio.getEffect('testeffect').type, 'check effect type')
  219. test:assertEquals(10, love.audio.getEffect('testeffect').volume, 'check effect volume')
  220. end
  221. -- love.audio.getMaxSceneEffects
  222. -- @NOTE feel like this is platform specific number so best we can do is a nil?
  223. love.test.audio.getMaxSceneEffects = function(test)
  224. test:assertNotNil(love.audio.getMaxSceneEffects())
  225. end
  226. -- love.audio.getMaxSourceEffects
  227. -- @NOTE feel like this is platform specific number so best we can do is a nil?
  228. love.test.audio.getMaxSourceEffects = function(test)
  229. test:assertNotNil(love.audio.getMaxSourceEffects())
  230. end
  231. -- love.audio.getOrientation
  232. -- @NOTE is there an expected default listener pos?
  233. love.test.audio.getOrientation = function(test)
  234. -- checking getting values matches what was set
  235. love.audio.setOrientation(1, 2, 3, 4, 5, 6)
  236. local fx, fy, fz, ux, uy, uz = love.audio.getOrientation()
  237. test:assertEquals(1, fx, 'check fx orientation')
  238. test:assertEquals(2, fy, 'check fy orientation')
  239. test:assertEquals(3, fz, 'check fz orientation')
  240. test:assertEquals(4, ux, 'check ux orientation')
  241. test:assertEquals(5, uy, 'check uy orientation')
  242. test:assertEquals(6, uz, 'check uz orientation')
  243. end
  244. -- love.audio.getPosition
  245. -- @NOTE is there an expected default listener pos?
  246. love.test.audio.getPosition = function(test)
  247. -- check getting values matches what was set
  248. love.audio.setPosition(1, 2, 3)
  249. local x, y, z = love.audio.getPosition()
  250. test:assertEquals(1, x, 'check x position')
  251. test:assertEquals(2, y, 'check y position')
  252. test:assertEquals(3, z, 'check z position')
  253. end
  254. -- love.audio.getRecordingDevices
  255. -- @NOTE hardware dependent so best can do is not nil check
  256. love.test.audio.getRecordingDevices = function(test)
  257. test:assertNotNil(love.audio.getRecordingDevices())
  258. end
  259. -- love.audio.getVelocity
  260. love.test.audio.getVelocity = function(test)
  261. -- check getting values matches what was set
  262. love.audio.setVelocity(1, 2, 3)
  263. local x, y, z = love.audio.getVelocity()
  264. test:assertEquals(1, x, 'check x velocity')
  265. test:assertEquals(2, y, 'check y velocity')
  266. test:assertEquals(3, z, 'check z velocity')
  267. end
  268. -- love.audio.getVolume
  269. love.test.audio.getVolume = function(test)
  270. -- check getting values matches what was set
  271. love.audio.setVolume(0.5)
  272. test:assertEquals(0.5, love.audio.getVolume(), 'check matches set')
  273. end
  274. -- love.audio.isEffectsSupported
  275. love.test.audio.isEffectsSupported = function(test)
  276. test:assertNotNil(love.audio.isEffectsSupported())
  277. end
  278. -- love.audio.newQueueableSource
  279. -- @NOTE this is just basic nil checking, objs have their own test method
  280. love.test.audio.newQueueableSource = function(test)
  281. test:assertObject(love.audio.newQueueableSource(32, 8, 1, 8))
  282. end
  283. -- love.audio.newSource
  284. -- @NOTE this is just basic nil checking, objs have their own test method
  285. love.test.audio.newSource = function(test)
  286. test:assertObject(love.audio.newSource('resources/click.ogg', 'static'))
  287. test:assertObject(love.audio.newSource('resources/click.ogg', 'stream'))
  288. end
  289. -- love.audio.pause
  290. love.test.audio.pause = function(test)
  291. -- check nothing paused (as should be nothing playing)
  292. local nopauses = love.audio.pause()
  293. test:assertEquals(0, #nopauses, 'check nothing paused')
  294. -- check 1 source paused after playing/pausing 1
  295. local source = love.audio.newSource('resources/click.ogg', 'static')
  296. love.audio.play(source)
  297. local onepause = love.audio.pause()
  298. test:assertEquals(1, #onepause, 'check 1 paused')
  299. end
  300. -- love.audio.play
  301. love.test.audio.play = function(test)
  302. -- check playing source is detected
  303. local source = love.audio.newSource('resources/click.ogg', 'static')
  304. love.audio.play(source)
  305. test:assertTrue(source:isPlaying(), 'check something playing')
  306. love.audio.pause()
  307. end
  308. -- love.audio.setDistanceModel
  309. love.test.audio.setDistanceModel = function(test)
  310. -- check setting each of the distance models is accepted and val returned
  311. local distancemodel = {
  312. 'none', 'inverse', 'inverseclamped', 'linear', 'linearclamped',
  313. 'exponent', 'exponentclamped'
  314. }
  315. for d=1,#distancemodel do
  316. love.audio.setDistanceModel(distancemodel[d])
  317. test:assertEquals(distancemodel[d], love.audio.getDistanceModel(),
  318. 'check model set to ' .. distancemodel[d])
  319. end
  320. end
  321. -- love.audio.setDopplerScale
  322. love.test.audio.setDopplerScale = function(test)
  323. -- check setting value is returned properly
  324. love.audio.setDopplerScale(0)
  325. test:assertEquals(0, love.audio.getDopplerScale(), 'check set to 0')
  326. love.audio.setDopplerScale(1)
  327. test:assertEquals(1, love.audio.getDopplerScale(), 'check set to 1')
  328. end
  329. -- love.audio.setEffect
  330. love.test.audio.setEffect = function(test)
  331. -- check effect is set correctly
  332. local effect = love.audio.setEffect('testeffect', {
  333. type = 'chorus',
  334. volume = 10
  335. })
  336. test:assertTrue(effect, 'check effect created')
  337. -- check values set match
  338. local settings = love.audio.getEffect('testeffect')
  339. test:assertEquals('chorus', settings.type, 'check effect type')
  340. test:assertEquals(10, settings.volume, 'check effect volume')
  341. end
  342. -- love.audio.setMixWithSystem
  343. love.test.audio.setMixWithSystem = function(test)
  344. test:assertNotNil(love.audio.setMixWithSystem(true))
  345. end
  346. -- love.audio.setOrientation
  347. love.test.audio.setOrientation = function(test)
  348. -- check setting orientation vals are returned
  349. love.audio.setOrientation(1, 2, 3, 4, 5, 6)
  350. local fx, fy, fz, ux, uy, uz = love.audio.getOrientation()
  351. test:assertEquals(1, fx, 'check fx orientation')
  352. test:assertEquals(2, fy, 'check fy orientation')
  353. test:assertEquals(3, fz, 'check fz orientation')
  354. test:assertEquals(4, ux, 'check ux orientation')
  355. test:assertEquals(5, uy, 'check uy orientation')
  356. test:assertEquals(6, uz, 'check uz orientation')
  357. end
  358. -- love.audio.setPosition
  359. love.test.audio.setPosition = function(test)
  360. -- check setting position vals are returned
  361. love.audio.setPosition(1, 2, 3)
  362. local x, y, z = love.audio.getPosition()
  363. test:assertEquals(1, x, 'check x position')
  364. test:assertEquals(2, y, 'check y position')
  365. test:assertEquals(3, z, 'check z position')
  366. end
  367. -- love.audio.setVelocity
  368. love.test.audio.setVelocity = function(test)
  369. -- check setting velocity vals are returned
  370. love.audio.setVelocity(1, 2, 3)
  371. local x, y, z = love.audio.getVelocity()
  372. test:assertEquals(1, x, 'check x velocity')
  373. test:assertEquals(2, y, 'check y velocity')
  374. test:assertEquals(3, z, 'check z velocity')
  375. end
  376. -- love.audio.setVolume
  377. love.test.audio.setVolume = function(test)
  378. -- check setting volume works
  379. love.audio.setVolume(0.5)
  380. test:assertEquals(0.5, love.audio.getVolume(), 'check set to 0.5')
  381. end
  382. -- love.audio.stop
  383. love.test.audio.stop = function(test)
  384. -- check source is playing first
  385. local source = love.audio.newSource('resources/click.ogg', 'static')
  386. love.audio.play(source)
  387. test:assertTrue(source:isPlaying(), 'check is playing')
  388. -- check source is then stopped
  389. love.audio.stop()
  390. test:assertFalse(source:isPlaying(), 'check stopped playing')
  391. end