raudio.c 108 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894
  1. /**********************************************************************************************
  2. *
  3. * raudio v1.1 - A simple and easy-to-use audio library based on miniaudio
  4. *
  5. * FEATURES:
  6. * - Manage audio device (init/close)
  7. * - Manage raw audio context
  8. * - Manage mixing channels
  9. * - Load and unload audio files
  10. * - Format wave data (sample rate, size, channels)
  11. * - Play/Stop/Pause/Resume loaded audio
  12. *
  13. * CONFIGURATION:
  14. * #define SUPPORT_MODULE_RAUDIO
  15. * raudio module is included in the build
  16. *
  17. * #define RAUDIO_STANDALONE
  18. * Define to use the module as standalone library (independently of raylib)
  19. * Required types and functions are defined in the same module
  20. *
  21. * #define SUPPORT_FILEFORMAT_WAV
  22. * #define SUPPORT_FILEFORMAT_OGG
  23. * #define SUPPORT_FILEFORMAT_MP3
  24. * #define SUPPORT_FILEFORMAT_QOA
  25. * #define SUPPORT_FILEFORMAT_FLAC
  26. * #define SUPPORT_FILEFORMAT_XM
  27. * #define SUPPORT_FILEFORMAT_MOD
  28. * Selected desired fileformats to be supported for loading. Some of those formats are
  29. * supported by default, to remove support, just comment unrequired #define in this module
  30. *
  31. * DEPENDENCIES:
  32. * miniaudio.h - Audio device management lib (https://github.com/mackron/miniaudio)
  33. * stb_vorbis.h - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
  34. * dr_wav.h - WAV audio files loading (http://github.com/mackron/dr_libs)
  35. * dr_mp3.h - MP3 audio file loading (https://github.com/mackron/dr_libs)
  36. * dr_flac.h - FLAC audio file loading (https://github.com/mackron/dr_libs)
  37. * jar_xm.h - XM module file loading
  38. * jar_mod.h - MOD audio file loading
  39. *
  40. * CONTRIBUTORS:
  41. * David Reid (github: @mackron) (Nov. 2017):
  42. * - Complete port to miniaudio library
  43. *
  44. * Joshua Reisenauer (github: @kd7tck) (2015):
  45. * - XM audio module support (jar_xm)
  46. * - MOD audio module support (jar_mod)
  47. * - Mixing channels support
  48. * - Raw audio context support
  49. *
  50. *
  51. * LICENSE: zlib/libpng
  52. *
  53. * Copyright (c) 2013-2025 Ramon Santamaria (@raysan5)
  54. *
  55. * This software is provided "as-is", without any express or implied warranty. In no event
  56. * will the authors be held liable for any damages arising from the use of this software.
  57. *
  58. * Permission is granted to anyone to use this software for any purpose, including commercial
  59. * applications, and to alter it and redistribute it freely, subject to the following restrictions:
  60. *
  61. * 1. The origin of this software must not be misrepresented; you must not claim that you
  62. * wrote the original software. If you use this software in a product, an acknowledgment
  63. * in the product documentation would be appreciated but is not required.
  64. *
  65. * 2. Altered source versions must be plainly marked as such, and must not be misrepresented
  66. * as being the original software.
  67. *
  68. * 3. This notice may not be removed or altered from any source distribution.
  69. *
  70. **********************************************************************************************/
  71. #if defined(RAUDIO_STANDALONE)
  72. #include "raudio.h"
  73. #else
  74. #include "raylib.h" // Declares module functions
  75. // Check if config flags have been externally provided on compilation line
  76. #if !defined(EXTERNAL_CONFIG_FLAGS)
  77. #include "config.h" // Defines module configuration flags
  78. #endif
  79. #include "utils.h" // Required for: fopen() Android mapping
  80. #endif
  81. #if defined(SUPPORT_MODULE_RAUDIO) || defined(RAUDIO_STANDALONE)
  82. #if defined(_WIN32)
  83. // To avoid conflicting windows.h symbols with raylib, some flags are defined
  84. // WARNING: Those flags avoid inclusion of some Win32 headers that could be required
  85. // by user at some point and won't be included...
  86. //-------------------------------------------------------------------------------------
  87. // If defined, the following flags inhibit definition of the indicated items
  88. #define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
  89. #define NOVIRTUALKEYCODES // VK_*
  90. #define NOWINMESSAGES // WM_*, EM_*, LB_*, CB_*
  91. #define NOWINSTYLES // WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
  92. #define NOSYSMETRICS // SM_*
  93. #define NOMENUS // MF_*
  94. #define NOICONS // IDI_*
  95. #define NOKEYSTATES // MK_*
  96. #define NOSYSCOMMANDS // SC_*
  97. #define NORASTEROPS // Binary and Tertiary raster ops
  98. #define NOSHOWWINDOW // SW_*
  99. #define OEMRESOURCE // OEM Resource values
  100. #define NOATOM // Atom Manager routines
  101. #define NOCLIPBOARD // Clipboard routines
  102. #define NOCOLOR // Screen colors
  103. #define NOCTLMGR // Control and Dialog routines
  104. #define NODRAWTEXT // DrawText() and DT_*
  105. #define NOGDI // All GDI defines and routines
  106. #define NOKERNEL // All KERNEL defines and routines
  107. #define NOUSER // All USER defines and routines
  108. //#define NONLS // All NLS defines and routines
  109. #define NOMB // MB_* and MessageBox()
  110. #define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
  111. #define NOMETAFILE // typedef METAFILEPICT
  112. #define NOMINMAX // Macros min(a,b) and max(a,b)
  113. #define NOMSG // typedef MSG and associated routines
  114. #define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
  115. #define NOSCROLL // SB_* and scrolling routines
  116. #define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
  117. #define NOSOUND // Sound driver routines
  118. #define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
  119. #define NOWH // SetWindowsHook and WH_*
  120. #define NOWINOFFSETS // GWL_*, GCL_*, associated routines
  121. #define NOCOMM // COMM driver routines
  122. #define NOKANJI // Kanji support stuff
  123. #define NOHELP // Help engine interface
  124. #define NOPROFILER // Profiler interface
  125. #define NODEFERWINDOWPOS // DeferWindowPos routines
  126. #define NOMCX // Modem Configuration Extensions
  127. // Type required before windows.h inclusion
  128. typedef struct tagMSG *LPMSG;
  129. #include <windows.h> // Windows functionality (miniaudio)
  130. // Type required by some unused function...
  131. typedef struct tagBITMAPINFOHEADER {
  132. DWORD biSize;
  133. LONG biWidth;
  134. LONG biHeight;
  135. WORD biPlanes;
  136. WORD biBitCount;
  137. DWORD biCompression;
  138. DWORD biSizeImage;
  139. LONG biXPelsPerMeter;
  140. LONG biYPelsPerMeter;
  141. DWORD biClrUsed;
  142. DWORD biClrImportant;
  143. } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
  144. #include <objbase.h> // Component Object Model (COM) header
  145. #include <mmreg.h> // Windows Multimedia, defines some WAVE structs
  146. #include <mmsystem.h> // Windows Multimedia, used by Windows GDI, defines DIBINDEX macro
  147. // Some required types defined for MSVC/TinyC compiler
  148. #if defined(_MSC_VER) || defined(__TINYC__)
  149. #include "propidl.h"
  150. #endif
  151. #endif
  152. #define MA_MALLOC RL_MALLOC
  153. #define MA_FREE RL_FREE
  154. #define MA_NO_JACK
  155. #define MA_NO_WAV
  156. #define MA_NO_FLAC
  157. #define MA_NO_MP3
  158. #define MA_NO_RESOURCE_MANAGER
  159. #define MA_NO_NODE_GRAPH
  160. #define MA_NO_ENGINE
  161. #define MA_NO_GENERATION
  162. // Threading model: Default: [0] COINIT_MULTITHREADED: COM calls objects on any thread (free threading)
  163. #define MA_COINIT_VALUE 2 // [2] COINIT_APARTMENTTHREADED: Each object has its own thread (apartment model)
  164. #define MINIAUDIO_IMPLEMENTATION
  165. //#define MA_DEBUG_OUTPUT
  166. #include "external/miniaudio.h" // Audio device initialization and management
  167. #undef PlaySound // Win32 API: windows.h > mmsystem.h defines PlaySound macro
  168. #include <stdlib.h> // Required for: malloc(), free()
  169. #include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
  170. #include <string.h> // Required for: strcmp() [Used in IsFileExtension(), LoadWaveFromMemory(), LoadMusicStreamFromMemory()]
  171. #if defined(RAUDIO_STANDALONE)
  172. #ifndef TRACELOG
  173. #define TRACELOG(level, ...) printf(__VA_ARGS__)
  174. #endif
  175. // Allow custom memory allocators
  176. #ifndef RL_MALLOC
  177. #define RL_MALLOC(sz) malloc(sz)
  178. #endif
  179. #ifndef RL_CALLOC
  180. #define RL_CALLOC(n,sz) calloc(n,sz)
  181. #endif
  182. #ifndef RL_REALLOC
  183. #define RL_REALLOC(ptr,sz) realloc(ptr,sz)
  184. #endif
  185. #ifndef RL_FREE
  186. #define RL_FREE(ptr) free(ptr)
  187. #endif
  188. #endif
  189. #if defined(SUPPORT_FILEFORMAT_WAV)
  190. #define DRWAV_MALLOC RL_MALLOC
  191. #define DRWAV_REALLOC RL_REALLOC
  192. #define DRWAV_FREE RL_FREE
  193. #define DR_WAV_IMPLEMENTATION
  194. #include "external/dr_wav.h" // WAV loading functions
  195. #endif
  196. #if defined(SUPPORT_FILEFORMAT_OGG)
  197. // TODO: Remap stb_vorbis malloc()/free() calls to RL_MALLOC/RL_FREE
  198. #include "external/stb_vorbis.c" // OGG loading functions
  199. #endif
  200. #if defined(SUPPORT_FILEFORMAT_MP3)
  201. #define DRMP3_MALLOC RL_MALLOC
  202. #define DRMP3_REALLOC RL_REALLOC
  203. #define DRMP3_FREE RL_FREE
  204. #define DR_MP3_IMPLEMENTATION
  205. #include "external/dr_mp3.h" // MP3 loading functions
  206. #endif
  207. #if defined(SUPPORT_FILEFORMAT_QOA)
  208. #define QOA_MALLOC RL_MALLOC
  209. #define QOA_FREE RL_FREE
  210. #if defined(_MSC_VER) // Disable some MSVC warning
  211. #pragma warning(push)
  212. #pragma warning(disable : 4018)
  213. #pragma warning(disable : 4267)
  214. #pragma warning(disable : 4244)
  215. #endif
  216. #define QOA_IMPLEMENTATION
  217. #include "external/qoa.h" // QOA loading and saving functions
  218. #include "external/qoaplay.c" // QOA stream playing helper functions
  219. #if defined(_MSC_VER)
  220. #pragma warning(pop) // Disable MSVC warning suppression
  221. #endif
  222. #endif
  223. #if defined(SUPPORT_FILEFORMAT_FLAC)
  224. #define DRFLAC_MALLOC RL_MALLOC
  225. #define DRFLAC_REALLOC RL_REALLOC
  226. #define DRFLAC_FREE RL_FREE
  227. #define DR_FLAC_IMPLEMENTATION
  228. #define DR_FLAC_NO_WIN32_IO
  229. #include "external/dr_flac.h" // FLAC loading functions
  230. #endif
  231. #if defined(SUPPORT_FILEFORMAT_XM)
  232. #define JARXM_MALLOC RL_MALLOC
  233. #define JARXM_FREE RL_FREE
  234. #if defined(_MSC_VER) // Disable some MSVC warning
  235. #pragma warning(push)
  236. #pragma warning(disable : 4244)
  237. #endif
  238. #define JAR_XM_IMPLEMENTATION
  239. #include "external/jar_xm.h" // XM loading functions
  240. #if defined(_MSC_VER)
  241. #pragma warning(pop) // Disable MSVC warning suppression
  242. #endif
  243. #endif
  244. #if defined(SUPPORT_FILEFORMAT_MOD)
  245. #define JARMOD_MALLOC RL_MALLOC
  246. #define JARMOD_FREE RL_FREE
  247. #define JAR_MOD_IMPLEMENTATION
  248. #include "external/jar_mod.h" // MOD loading functions
  249. #endif
  250. //----------------------------------------------------------------------------------
  251. // Defines and Macros
  252. //----------------------------------------------------------------------------------
  253. #ifndef AUDIO_DEVICE_FORMAT
  254. #define AUDIO_DEVICE_FORMAT ma_format_f32 // Device output format (float-32bit)
  255. #endif
  256. #ifndef AUDIO_DEVICE_CHANNELS
  257. #define AUDIO_DEVICE_CHANNELS 2 // Device output channels: stereo
  258. #endif
  259. #ifndef AUDIO_DEVICE_SAMPLE_RATE
  260. #define AUDIO_DEVICE_SAMPLE_RATE 0 // Device output sample rate
  261. #endif
  262. #ifndef MAX_AUDIO_BUFFER_POOL_CHANNELS
  263. #define MAX_AUDIO_BUFFER_POOL_CHANNELS 16 // Audio pool channels
  264. #endif
  265. //----------------------------------------------------------------------------------
  266. // Types and Structures Definition
  267. //----------------------------------------------------------------------------------
  268. #if defined(RAUDIO_STANDALONE)
  269. // Trace log level
  270. // NOTE: Organized by priority level
  271. typedef enum {
  272. LOG_ALL = 0, // Display all logs
  273. LOG_TRACE, // Trace logging, intended for internal use only
  274. LOG_DEBUG, // Debug logging, used for internal debugging, it should be disabled on release builds
  275. LOG_INFO, // Info logging, used for program execution info
  276. LOG_WARNING, // Warning logging, used on recoverable failures
  277. LOG_ERROR, // Error logging, used on unrecoverable failures
  278. LOG_FATAL, // Fatal logging, used to abort program: exit(EXIT_FAILURE)
  279. LOG_NONE // Disable logging
  280. } TraceLogLevel;
  281. #endif
  282. // Music context type
  283. // NOTE: Depends on data structure provided by the library
  284. // in charge of reading the different file types
  285. typedef enum {
  286. MUSIC_AUDIO_NONE = 0, // No audio context loaded
  287. MUSIC_AUDIO_WAV, // WAV audio context
  288. MUSIC_AUDIO_OGG, // OGG audio context
  289. MUSIC_AUDIO_FLAC, // FLAC audio context
  290. MUSIC_AUDIO_MP3, // MP3 audio context
  291. MUSIC_AUDIO_QOA, // QOA audio context
  292. MUSIC_MODULE_XM, // XM module audio context
  293. MUSIC_MODULE_MOD // MOD module audio context
  294. } MusicContextType;
  295. // NOTE: Different logic is used when feeding data to the playback device
  296. // depending on whether data is streamed (Music vs Sound)
  297. typedef enum {
  298. AUDIO_BUFFER_USAGE_STATIC = 0,
  299. AUDIO_BUFFER_USAGE_STREAM
  300. } AudioBufferUsage;
  301. // Audio buffer struct
  302. struct rAudioBuffer {
  303. ma_data_converter converter; // Audio data converter
  304. AudioCallback callback; // Audio buffer callback for buffer filling on audio threads
  305. rAudioProcessor *processor; // Audio processor
  306. float volume; // Audio buffer volume
  307. float pitch; // Audio buffer pitch
  308. float pan; // Audio buffer pan (0.0f to 1.0f)
  309. bool playing; // Audio buffer state: AUDIO_PLAYING
  310. bool paused; // Audio buffer state: AUDIO_PAUSED
  311. bool looping; // Audio buffer looping, default to true for AudioStreams
  312. int usage; // Audio buffer usage mode: STATIC or STREAM
  313. bool isSubBufferProcessed[2]; // SubBuffer processed (virtual double buffer)
  314. unsigned int sizeInFrames; // Total buffer size in frames
  315. unsigned int frameCursorPos; // Frame cursor position
  316. unsigned int framesProcessed; // Total frames processed in this buffer (required for play timing)
  317. unsigned char *data; // Data buffer, on music stream keeps filling
  318. rAudioBuffer *next; // Next audio buffer on the list
  319. rAudioBuffer *prev; // Previous audio buffer on the list
  320. };
  321. // Audio processor struct
  322. // NOTE: Useful to apply effects to an AudioBuffer
  323. struct rAudioProcessor {
  324. AudioCallback process; // Processor callback function
  325. rAudioProcessor *next; // Next audio processor on the list
  326. rAudioProcessor *prev; // Previous audio processor on the list
  327. };
  328. #define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision
  329. // Audio data context
  330. typedef struct AudioData {
  331. struct {
  332. ma_context context; // miniaudio context data
  333. ma_device device; // miniaudio device
  334. ma_mutex lock; // miniaudio mutex lock
  335. bool isReady; // Check if audio device is ready
  336. size_t pcmBufferSize; // Pre-allocated buffer size
  337. void *pcmBuffer; // Pre-allocated buffer to read audio data from file/memory
  338. } System;
  339. struct {
  340. AudioBuffer *first; // Pointer to first AudioBuffer in the list
  341. AudioBuffer *last; // Pointer to last AudioBuffer in the list
  342. int defaultSize; // Default audio buffer size for audio streams
  343. } Buffer;
  344. rAudioProcessor *mixedProcessor;
  345. } AudioData;
  346. //----------------------------------------------------------------------------------
  347. // Global Variables Definition
  348. //----------------------------------------------------------------------------------
  349. static AudioData AUDIO = { // Global AUDIO context
  350. // NOTE: Music buffer size is defined by number of samples, independent of sample size and channels number
  351. // After some math, considering a sampleRate of 48000, a buffer refill rate of 1/60 seconds and a
  352. // standard double-buffering system, a 4096 samples buffer has been chosen, it should be enough
  353. // In case of music-stalls, just increase this number
  354. .Buffer.defaultSize = 0,
  355. .mixedProcessor = NULL
  356. };
  357. //----------------------------------------------------------------------------------
  358. // Module Internal Functions Declaration
  359. //----------------------------------------------------------------------------------
  360. static void OnLog(void *pUserData, ma_uint32 level, const char *pMessage);
  361. // Reads audio data from an AudioBuffer object in internal/device formats
  362. static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount);
  363. static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount);
  364. static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount);
  365. static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer);
  366. static bool IsAudioBufferPlayingInLockedState(AudioBuffer *buffer);
  367. static void StopAudioBufferInLockedState(AudioBuffer *buffer);
  368. static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data, int frameCount);
  369. #if defined(RAUDIO_STANDALONE)
  370. static bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
  371. static const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes the dot: .png)
  372. static const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
  373. static const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
  374. static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
  375. static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write)
  376. static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
  377. #endif
  378. //----------------------------------------------------------------------------------
  379. // AudioBuffer management functions declaration
  380. // NOTE: Those functions are not exposed by raylib... for the moment
  381. //----------------------------------------------------------------------------------
  382. AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames, int usage);
  383. void UnloadAudioBuffer(AudioBuffer *buffer);
  384. bool IsAudioBufferPlaying(AudioBuffer *buffer);
  385. void PlayAudioBuffer(AudioBuffer *buffer);
  386. void StopAudioBuffer(AudioBuffer *buffer);
  387. void PauseAudioBuffer(AudioBuffer *buffer);
  388. void ResumeAudioBuffer(AudioBuffer *buffer);
  389. void SetAudioBufferVolume(AudioBuffer *buffer, float volume);
  390. void SetAudioBufferPitch(AudioBuffer *buffer, float pitch);
  391. void SetAudioBufferPan(AudioBuffer *buffer, float pan);
  392. void TrackAudioBuffer(AudioBuffer *buffer);
  393. void UntrackAudioBuffer(AudioBuffer *buffer);
  394. //----------------------------------------------------------------------------------
  395. // Module Functions Definition - Audio Device initialization and Closing
  396. //----------------------------------------------------------------------------------
  397. // Initialize audio device
  398. void InitAudioDevice(void)
  399. {
  400. // Init audio context
  401. ma_context_config ctxConfig = ma_context_config_init();
  402. ma_log_callback_init(OnLog, NULL);
  403. ma_result result = ma_context_init(NULL, 0, &ctxConfig, &AUDIO.System.context);
  404. if (result != MA_SUCCESS)
  405. {
  406. TRACELOG(LOG_WARNING, "AUDIO: Failed to initialize context");
  407. return;
  408. }
  409. // Init audio device
  410. // NOTE: Using the default device. Format is floating point because it simplifies mixing
  411. ma_device_config config = ma_device_config_init(ma_device_type_playback);
  412. config.playback.pDeviceID = NULL; // NULL for the default playback AUDIO.System.device
  413. config.playback.format = AUDIO_DEVICE_FORMAT;
  414. config.playback.channels = AUDIO_DEVICE_CHANNELS;
  415. config.capture.pDeviceID = NULL; // NULL for the default capture AUDIO.System.device
  416. config.capture.format = ma_format_s16;
  417. config.capture.channels = 1;
  418. config.sampleRate = AUDIO_DEVICE_SAMPLE_RATE;
  419. config.dataCallback = OnSendAudioDataToDevice;
  420. config.pUserData = NULL;
  421. result = ma_device_init(&AUDIO.System.context, &config, &AUDIO.System.device);
  422. if (result != MA_SUCCESS)
  423. {
  424. TRACELOG(LOG_WARNING, "AUDIO: Failed to initialize playback device");
  425. ma_context_uninit(&AUDIO.System.context);
  426. return;
  427. }
  428. // Mixing happens on a separate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
  429. // want to look at something a bit smarter later on to keep everything real-time, if that's necessary
  430. if (ma_mutex_init(&AUDIO.System.lock) != MA_SUCCESS)
  431. {
  432. TRACELOG(LOG_WARNING, "AUDIO: Failed to create mutex for mixing");
  433. ma_device_uninit(&AUDIO.System.device);
  434. ma_context_uninit(&AUDIO.System.context);
  435. return;
  436. }
  437. // Keep the device running the whole time. May want to consider doing something a bit smarter and only have the device running
  438. // while there's at least one sound being played
  439. result = ma_device_start(&AUDIO.System.device);
  440. if (result != MA_SUCCESS)
  441. {
  442. TRACELOG(LOG_WARNING, "AUDIO: Failed to start playback device");
  443. ma_device_uninit(&AUDIO.System.device);
  444. ma_context_uninit(&AUDIO.System.context);
  445. return;
  446. }
  447. TRACELOG(LOG_INFO, "AUDIO: Device initialized successfully");
  448. TRACELOG(LOG_INFO, " > Backend: miniaudio | %s", ma_get_backend_name(AUDIO.System.context.backend));
  449. TRACELOG(LOG_INFO, " > Format: %s -> %s", ma_get_format_name(AUDIO.System.device.playback.format), ma_get_format_name(AUDIO.System.device.playback.internalFormat));
  450. TRACELOG(LOG_INFO, " > Channels: %d -> %d", AUDIO.System.device.playback.channels, AUDIO.System.device.playback.internalChannels);
  451. TRACELOG(LOG_INFO, " > Sample rate: %d -> %d", AUDIO.System.device.sampleRate, AUDIO.System.device.playback.internalSampleRate);
  452. TRACELOG(LOG_INFO, " > Periods size: %d", AUDIO.System.device.playback.internalPeriodSizeInFrames*AUDIO.System.device.playback.internalPeriods);
  453. AUDIO.System.isReady = true;
  454. }
  455. // Close the audio device for all contexts
  456. void CloseAudioDevice(void)
  457. {
  458. if (AUDIO.System.isReady)
  459. {
  460. ma_mutex_uninit(&AUDIO.System.lock);
  461. ma_device_uninit(&AUDIO.System.device);
  462. ma_context_uninit(&AUDIO.System.context);
  463. AUDIO.System.isReady = false;
  464. RL_FREE(AUDIO.System.pcmBuffer);
  465. AUDIO.System.pcmBuffer = NULL;
  466. AUDIO.System.pcmBufferSize = 0;
  467. TRACELOG(LOG_INFO, "AUDIO: Device closed successfully");
  468. }
  469. else TRACELOG(LOG_WARNING, "AUDIO: Device could not be closed, not currently initialized");
  470. }
  471. // Check if device has been initialized successfully
  472. bool IsAudioDeviceReady(void)
  473. {
  474. return AUDIO.System.isReady;
  475. }
  476. // Set master volume (listener)
  477. void SetMasterVolume(float volume)
  478. {
  479. ma_device_set_master_volume(&AUDIO.System.device, volume);
  480. }
  481. // Get master volume (listener)
  482. float GetMasterVolume(void)
  483. {
  484. float volume = 0.0f;
  485. ma_device_get_master_volume(&AUDIO.System.device, &volume);
  486. return volume;
  487. }
  488. //----------------------------------------------------------------------------------
  489. // Module Functions Definition - Audio Buffer management
  490. //----------------------------------------------------------------------------------
  491. // Initialize a new audio buffer (filled with silence)
  492. AudioBuffer *LoadAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames, int usage)
  493. {
  494. AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(1, sizeof(AudioBuffer));
  495. if (audioBuffer == NULL)
  496. {
  497. TRACELOG(LOG_WARNING, "AUDIO: Failed to allocate memory for buffer");
  498. return NULL;
  499. }
  500. if (sizeInFrames > 0) audioBuffer->data = RL_CALLOC(sizeInFrames*channels*ma_get_bytes_per_sample(format), 1);
  501. // Audio data runs through a format converter
  502. ma_data_converter_config converterConfig = ma_data_converter_config_init(format, AUDIO_DEVICE_FORMAT, channels, AUDIO_DEVICE_CHANNELS, sampleRate, AUDIO.System.device.sampleRate);
  503. converterConfig.allowDynamicSampleRate = true;
  504. ma_result result = ma_data_converter_init(&converterConfig, NULL, &audioBuffer->converter);
  505. if (result != MA_SUCCESS)
  506. {
  507. TRACELOG(LOG_WARNING, "AUDIO: Failed to create data conversion pipeline");
  508. RL_FREE(audioBuffer);
  509. return NULL;
  510. }
  511. // Init audio buffer values
  512. audioBuffer->volume = 1.0f;
  513. audioBuffer->pitch = 1.0f;
  514. audioBuffer->pan = 0.5f;
  515. audioBuffer->callback = NULL;
  516. audioBuffer->processor = NULL;
  517. audioBuffer->playing = false;
  518. audioBuffer->paused = false;
  519. audioBuffer->looping = false;
  520. audioBuffer->usage = usage;
  521. audioBuffer->frameCursorPos = 0;
  522. audioBuffer->framesProcessed = 0;
  523. audioBuffer->sizeInFrames = sizeInFrames;
  524. // Buffers should be marked as processed by default so that a call to
  525. // UpdateAudioStream() immediately after initialization works correctly
  526. audioBuffer->isSubBufferProcessed[0] = true;
  527. audioBuffer->isSubBufferProcessed[1] = true;
  528. // Track audio buffer to linked list next position
  529. TrackAudioBuffer(audioBuffer);
  530. return audioBuffer;
  531. }
  532. // Delete an audio buffer
  533. void UnloadAudioBuffer(AudioBuffer *buffer)
  534. {
  535. if (buffer != NULL)
  536. {
  537. UntrackAudioBuffer(buffer);
  538. ma_data_converter_uninit(&buffer->converter, NULL);
  539. RL_FREE(buffer->data);
  540. RL_FREE(buffer);
  541. }
  542. }
  543. // Check if an audio buffer is playing from a program state without lock
  544. bool IsAudioBufferPlaying(AudioBuffer *buffer)
  545. {
  546. bool result = false;
  547. ma_mutex_lock(&AUDIO.System.lock);
  548. result = IsAudioBufferPlayingInLockedState(buffer);
  549. ma_mutex_unlock(&AUDIO.System.lock);
  550. return result;
  551. }
  552. // Play an audio buffer
  553. // NOTE: Buffer is restarted to the start
  554. // Use PauseAudioBuffer() and ResumeAudioBuffer() if the playback position should be maintained
  555. void PlayAudioBuffer(AudioBuffer *buffer)
  556. {
  557. if (buffer != NULL)
  558. {
  559. ma_mutex_lock(&AUDIO.System.lock);
  560. buffer->playing = true;
  561. buffer->paused = false;
  562. buffer->frameCursorPos = 0;
  563. buffer->framesProcessed = 0;
  564. buffer->isSubBufferProcessed[0] = true;
  565. buffer->isSubBufferProcessed[1] = true;
  566. ma_mutex_unlock(&AUDIO.System.lock);
  567. }
  568. }
  569. // Stop an audio buffer from a program state without lock
  570. void StopAudioBuffer(AudioBuffer *buffer)
  571. {
  572. ma_mutex_lock(&AUDIO.System.lock);
  573. StopAudioBufferInLockedState(buffer);
  574. ma_mutex_unlock(&AUDIO.System.lock);
  575. }
  576. // Pause an audio buffer
  577. void PauseAudioBuffer(AudioBuffer *buffer)
  578. {
  579. if (buffer != NULL)
  580. {
  581. ma_mutex_lock(&AUDIO.System.lock);
  582. buffer->paused = true;
  583. ma_mutex_unlock(&AUDIO.System.lock);
  584. }
  585. }
  586. // Resume an audio buffer
  587. void ResumeAudioBuffer(AudioBuffer *buffer)
  588. {
  589. if (buffer != NULL)
  590. {
  591. ma_mutex_lock(&AUDIO.System.lock);
  592. buffer->paused = false;
  593. ma_mutex_unlock(&AUDIO.System.lock);
  594. }
  595. }
  596. // Set volume for an audio buffer
  597. void SetAudioBufferVolume(AudioBuffer *buffer, float volume)
  598. {
  599. if (buffer != NULL)
  600. {
  601. ma_mutex_lock(&AUDIO.System.lock);
  602. buffer->volume = volume;
  603. ma_mutex_unlock(&AUDIO.System.lock);
  604. }
  605. }
  606. // Set pitch for an audio buffer
  607. void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
  608. {
  609. if ((buffer != NULL) && (pitch > 0.0f))
  610. {
  611. ma_mutex_lock(&AUDIO.System.lock);
  612. // Pitching is just an adjustment of the sample rate
  613. // Note that this changes the duration of the sound:
  614. // - higher pitches will make the sound faster
  615. // - lower pitches make it slower
  616. ma_uint32 outputSampleRate = (ma_uint32)((float)buffer->converter.sampleRateOut/pitch);
  617. ma_data_converter_set_rate(&buffer->converter, buffer->converter.sampleRateIn, outputSampleRate);
  618. buffer->pitch = pitch;
  619. ma_mutex_unlock(&AUDIO.System.lock);
  620. }
  621. }
  622. // Set pan for an audio buffer
  623. void SetAudioBufferPan(AudioBuffer *buffer, float pan)
  624. {
  625. if (pan < 0.0f) pan = 0.0f;
  626. else if (pan > 1.0f) pan = 1.0f;
  627. if (buffer != NULL)
  628. {
  629. ma_mutex_lock(&AUDIO.System.lock);
  630. buffer->pan = pan;
  631. ma_mutex_unlock(&AUDIO.System.lock);
  632. }
  633. }
  634. // Track audio buffer to linked list next position
  635. void TrackAudioBuffer(AudioBuffer *buffer)
  636. {
  637. ma_mutex_lock(&AUDIO.System.lock);
  638. {
  639. if (AUDIO.Buffer.first == NULL) AUDIO.Buffer.first = buffer;
  640. else
  641. {
  642. AUDIO.Buffer.last->next = buffer;
  643. buffer->prev = AUDIO.Buffer.last;
  644. }
  645. AUDIO.Buffer.last = buffer;
  646. }
  647. ma_mutex_unlock(&AUDIO.System.lock);
  648. }
  649. // Untrack audio buffer from linked list
  650. void UntrackAudioBuffer(AudioBuffer *buffer)
  651. {
  652. ma_mutex_lock(&AUDIO.System.lock);
  653. {
  654. if (buffer->prev == NULL) AUDIO.Buffer.first = buffer->next;
  655. else buffer->prev->next = buffer->next;
  656. if (buffer->next == NULL) AUDIO.Buffer.last = buffer->prev;
  657. else buffer->next->prev = buffer->prev;
  658. buffer->prev = NULL;
  659. buffer->next = NULL;
  660. }
  661. ma_mutex_unlock(&AUDIO.System.lock);
  662. }
  663. //----------------------------------------------------------------------------------
  664. // Module Functions Definition - Sounds loading and playing (.WAV)
  665. //----------------------------------------------------------------------------------
  666. // Load wave data from file
  667. Wave LoadWave(const char *fileName)
  668. {
  669. Wave wave = { 0 };
  670. // Loading file to memory
  671. int dataSize = 0;
  672. unsigned char *fileData = LoadFileData(fileName, &dataSize);
  673. // Loading wave from memory data
  674. if (fileData != NULL) wave = LoadWaveFromMemory(GetFileExtension(fileName), fileData, dataSize);
  675. UnloadFileData(fileData);
  676. return wave;
  677. }
  678. // Load wave from memory buffer, fileType refers to extension: i.e. ".wav"
  679. // WARNING: File extension must be provided in lower-case
  680. Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize)
  681. {
  682. Wave wave = { 0 };
  683. if (false) { }
  684. #if defined(SUPPORT_FILEFORMAT_WAV)
  685. else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
  686. {
  687. drwav wav = { 0 };
  688. bool success = drwav_init_memory(&wav, fileData, dataSize, NULL);
  689. if (success)
  690. {
  691. wave.frameCount = (unsigned int)wav.totalPCMFrameCount;
  692. wave.sampleRate = wav.sampleRate;
  693. wave.sampleSize = 16;
  694. wave.channels = wav.channels;
  695. wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short));
  696. // NOTE: We are forcing conversion to 16bit sample size on reading
  697. drwav_read_pcm_frames_s16(&wav, wave.frameCount, wave.data);
  698. }
  699. else TRACELOG(LOG_WARNING, "WAVE: Failed to load WAV data");
  700. drwav_uninit(&wav);
  701. }
  702. #endif
  703. #if defined(SUPPORT_FILEFORMAT_OGG)
  704. else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
  705. {
  706. stb_vorbis *oggData = stb_vorbis_open_memory((unsigned char *)fileData, dataSize, NULL, NULL);
  707. if (oggData != NULL)
  708. {
  709. stb_vorbis_info info = stb_vorbis_get_info(oggData);
  710. wave.sampleRate = info.sample_rate;
  711. wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
  712. wave.channels = info.channels;
  713. wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames!
  714. wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short));
  715. // NOTE: Get the number of samples to process (be careful! we ask for number of shorts, not bytes!)
  716. stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels);
  717. stb_vorbis_close(oggData);
  718. }
  719. else TRACELOG(LOG_WARNING, "WAVE: Failed to load OGG data");
  720. }
  721. #endif
  722. #if defined(SUPPORT_FILEFORMAT_MP3)
  723. else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
  724. {
  725. drmp3_config config = { 0 };
  726. unsigned long long int totalFrameCount = 0;
  727. // NOTE: We are forcing conversion to 32bit float sample size on reading
  728. wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL);
  729. wave.sampleSize = 32;
  730. if (wave.data != NULL)
  731. {
  732. wave.channels = config.channels;
  733. wave.sampleRate = config.sampleRate;
  734. wave.frameCount = (int)totalFrameCount;
  735. }
  736. else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
  737. }
  738. #endif
  739. #if defined(SUPPORT_FILEFORMAT_QOA)
  740. else if ((strcmp(fileType, ".qoa") == 0) || (strcmp(fileType, ".QOA") == 0))
  741. {
  742. qoa_desc qoa = { 0 };
  743. // NOTE: Returned sample data is always 16 bit?
  744. wave.data = qoa_decode(fileData, dataSize, &qoa);
  745. wave.sampleSize = 16;
  746. if (wave.data != NULL)
  747. {
  748. wave.channels = qoa.channels;
  749. wave.sampleRate = qoa.samplerate;
  750. wave.frameCount = qoa.samples;
  751. }
  752. else TRACELOG(LOG_WARNING, "WAVE: Failed to load QOA data");
  753. }
  754. #endif
  755. #if defined(SUPPORT_FILEFORMAT_FLAC)
  756. else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
  757. {
  758. unsigned long long int totalFrameCount = 0;
  759. // NOTE: We are forcing conversion to 16bit sample size on reading
  760. wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
  761. wave.sampleSize = 16;
  762. if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount;
  763. else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
  764. }
  765. #endif
  766. else TRACELOG(LOG_WARNING, "WAVE: Data format not supported");
  767. TRACELOG(LOG_INFO, "WAVE: Data loaded successfully (%i Hz, %i bit, %i channels)", wave.sampleRate, wave.sampleSize, wave.channels);
  768. return wave;
  769. }
  770. // Checks if wave data is valid (data loaded and parameters)
  771. bool IsWaveValid(Wave wave)
  772. {
  773. bool result = false;
  774. if ((wave.data != NULL) && // Validate wave data available
  775. (wave.frameCount > 0) && // Validate frame count
  776. (wave.sampleRate > 0) && // Validate sample rate is supported
  777. (wave.sampleSize > 0) && // Validate sample size is supported
  778. (wave.channels > 0)) result = true; // Validate number of channels supported
  779. return result;
  780. }
  781. // Load sound from file
  782. // NOTE: The entire file is loaded to memory to be played (no-streaming)
  783. Sound LoadSound(const char *fileName)
  784. {
  785. Wave wave = LoadWave(fileName);
  786. Sound sound = LoadSoundFromWave(wave);
  787. UnloadWave(wave); // Sound is loaded, we can unload wave
  788. return sound;
  789. }
  790. // Load sound from wave data
  791. // NOTE: Wave data must be unallocated manually
  792. Sound LoadSoundFromWave(Wave wave)
  793. {
  794. Sound sound = { 0 };
  795. if (wave.data != NULL)
  796. {
  797. // When using miniaudio we need to do our own mixing
  798. // To simplify this we need convert the format of each sound to be consistent with
  799. // the format used to open the playback AUDIO.System.device. We can do this two ways:
  800. //
  801. // 1) Convert the whole sound in one go at load time (here)
  802. // 2) Convert the audio data in chunks at mixing time
  803. //
  804. // First option has been selected, format conversion is done on the loading stage
  805. // The downside is that it uses more memory if the original sound is u8 or s16
  806. ma_format formatIn = ((wave.sampleSize == 8)? ma_format_u8 : ((wave.sampleSize == 16)? ma_format_s16 : ma_format_f32));
  807. ma_uint32 frameCountIn = wave.frameCount;
  808. ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, NULL, frameCountIn, formatIn, wave.channels, wave.sampleRate);
  809. if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed to get frame count for format conversion");
  810. AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, frameCount, AUDIO_BUFFER_USAGE_STATIC);
  811. if (audioBuffer == NULL)
  812. {
  813. TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
  814. return sound; // early return to avoid dereferencing the audioBuffer null pointer
  815. }
  816. frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, frameCount, AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, wave.data, frameCountIn, formatIn, wave.channels, wave.sampleRate);
  817. if (frameCount == 0) TRACELOG(LOG_WARNING, "SOUND: Failed format conversion");
  818. sound.frameCount = frameCount;
  819. sound.stream.sampleRate = AUDIO.System.device.sampleRate;
  820. sound.stream.sampleSize = 32;
  821. sound.stream.channels = AUDIO_DEVICE_CHANNELS;
  822. sound.stream.buffer = audioBuffer;
  823. }
  824. return sound;
  825. }
  826. // Clone sound from existing sound data, clone does not own wave data
  827. // NOTE: Wave data must be unallocated manually and will be shared across all clones
  828. Sound LoadSoundAlias(Sound source)
  829. {
  830. Sound sound = { 0 };
  831. if (source.stream.buffer->data != NULL)
  832. {
  833. AudioBuffer *audioBuffer = LoadAudioBuffer(AUDIO_DEVICE_FORMAT, AUDIO_DEVICE_CHANNELS, AUDIO.System.device.sampleRate, 0, AUDIO_BUFFER_USAGE_STATIC);
  834. if (audioBuffer == NULL)
  835. {
  836. TRACELOG(LOG_WARNING, "SOUND: Failed to create buffer");
  837. return sound; // Early return to avoid dereferencing the audioBuffer null pointer
  838. }
  839. audioBuffer->sizeInFrames = source.stream.buffer->sizeInFrames;
  840. audioBuffer->data = source.stream.buffer->data;
  841. // initalize the buffer as if it was new
  842. audioBuffer->volume = 1.0f;
  843. audioBuffer->pitch = 1.0f;
  844. audioBuffer->pan = 0.5f;
  845. sound.frameCount = source.frameCount;
  846. sound.stream.sampleRate = AUDIO.System.device.sampleRate;
  847. sound.stream.sampleSize = 32;
  848. sound.stream.channels = AUDIO_DEVICE_CHANNELS;
  849. sound.stream.buffer = audioBuffer;
  850. }
  851. return sound;
  852. }
  853. // Checks if a sound is valid (data loaded and buffers initialized)
  854. bool IsSoundValid(Sound sound)
  855. {
  856. bool result = false;
  857. if ((sound.frameCount > 0) && // Validate frame count
  858. (sound.stream.buffer != NULL) && // Validate stream buffer
  859. (sound.stream.sampleRate > 0) && // Validate sample rate is supported
  860. (sound.stream.sampleSize > 0) && // Validate sample size is supported
  861. (sound.stream.channels > 0)) result = true; // Validate number of channels supported
  862. return result;
  863. }
  864. // Unload wave data
  865. void UnloadWave(Wave wave)
  866. {
  867. RL_FREE(wave.data);
  868. //TRACELOG(LOG_INFO, "WAVE: Unloaded wave data from RAM");
  869. }
  870. // Unload sound
  871. void UnloadSound(Sound sound)
  872. {
  873. UnloadAudioBuffer(sound.stream.buffer);
  874. //TRACELOG(LOG_INFO, "SOUND: Unloaded sound data from RAM");
  875. }
  876. void UnloadSoundAlias(Sound alias)
  877. {
  878. // Untrack and unload just the sound buffer, not the sample data, it is shared with the source for the alias
  879. if (alias.stream.buffer != NULL)
  880. {
  881. UntrackAudioBuffer(alias.stream.buffer);
  882. ma_data_converter_uninit(&alias.stream.buffer->converter, NULL);
  883. RL_FREE(alias.stream.buffer);
  884. }
  885. }
  886. // Update sound buffer with new data
  887. // NOTE 1: data format must match sound.stream.sampleSize
  888. // NOTE 2: frameCount must not exceed sound.frameCount
  889. void UpdateSound(Sound sound, const void *data, int frameCount)
  890. {
  891. if (sound.stream.buffer != NULL)
  892. {
  893. StopAudioBuffer(sound.stream.buffer);
  894. memcpy(sound.stream.buffer->data, data, frameCount*ma_get_bytes_per_frame(sound.stream.buffer->converter.formatIn, sound.stream.buffer->converter.channelsIn));
  895. }
  896. }
  897. // Export wave data to file
  898. bool ExportWave(Wave wave, const char *fileName)
  899. {
  900. bool success = false;
  901. if (false) { }
  902. #if defined(SUPPORT_FILEFORMAT_WAV)
  903. else if (IsFileExtension(fileName, ".wav"))
  904. {
  905. drwav wav = { 0 };
  906. drwav_data_format format = { 0 };
  907. format.container = drwav_container_riff;
  908. if (wave.sampleSize == 32) format.format = DR_WAVE_FORMAT_IEEE_FLOAT;
  909. else format.format = DR_WAVE_FORMAT_PCM;
  910. format.channels = wave.channels;
  911. format.sampleRate = wave.sampleRate;
  912. format.bitsPerSample = wave.sampleSize;
  913. void *fileData = NULL;
  914. size_t fileDataSize = 0;
  915. success = drwav_init_memory_write(&wav, &fileData, &fileDataSize, &format, NULL);
  916. if (success) success = (int)drwav_write_pcm_frames(&wav, wave.frameCount, wave.data);
  917. drwav_result result = drwav_uninit(&wav);
  918. if (result == DRWAV_SUCCESS) success = SaveFileData(fileName, (unsigned char *)fileData, (unsigned int)fileDataSize);
  919. drwav_free(fileData, NULL);
  920. }
  921. #endif
  922. #if defined(SUPPORT_FILEFORMAT_QOA)
  923. else if (IsFileExtension(fileName, ".qoa"))
  924. {
  925. if (wave.sampleSize == 16)
  926. {
  927. qoa_desc qoa = { 0 };
  928. qoa.channels = wave.channels;
  929. qoa.samplerate = wave.sampleRate;
  930. qoa.samples = wave.frameCount;
  931. int bytesWritten = qoa_write(fileName, wave.data, &qoa);
  932. if (bytesWritten > 0) success = true;
  933. }
  934. else TRACELOG(LOG_WARNING, "AUDIO: Wave data must be 16 bit per sample for QOA format export");
  935. }
  936. #endif
  937. else if (IsFileExtension(fileName, ".raw"))
  938. {
  939. // Export raw sample data (without header)
  940. // NOTE: It's up to the user to track wave parameters
  941. success = SaveFileData(fileName, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
  942. }
  943. if (success) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave data exported successfully", fileName);
  944. else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave data", fileName);
  945. return success;
  946. }
  947. // Export wave sample data to code (.h)
  948. bool ExportWaveAsCode(Wave wave, const char *fileName)
  949. {
  950. bool success = false;
  951. #ifndef TEXT_BYTES_PER_LINE
  952. #define TEXT_BYTES_PER_LINE 20
  953. #endif
  954. int waveDataSize = wave.frameCount*wave.channels*wave.sampleSize/8;
  955. // NOTE: Text data buffer size is estimated considering wave data size in bytes
  956. // and requiring 12 char bytes for every byte; the actual size varies, but
  957. // the longest possible char being appended is "%.4ff,\n ", which is 12 bytes
  958. char *txtData = (char *)RL_CALLOC(waveDataSize*12 + 2000, sizeof(char));
  959. int byteCount = 0;
  960. byteCount += sprintf(txtData + byteCount, "\n//////////////////////////////////////////////////////////////////////////////////\n");
  961. byteCount += sprintf(txtData + byteCount, "// //\n");
  962. byteCount += sprintf(txtData + byteCount, "// WaveAsCode exporter v1.1 - Wave data exported as an array of bytes //\n");
  963. byteCount += sprintf(txtData + byteCount, "// //\n");
  964. byteCount += sprintf(txtData + byteCount, "// more info and bugs-report: github.com/raysan5/raylib //\n");
  965. byteCount += sprintf(txtData + byteCount, "// feedback and support: ray[at]raylib.com //\n");
  966. byteCount += sprintf(txtData + byteCount, "// //\n");
  967. byteCount += sprintf(txtData + byteCount, "// Copyright (c) 2018-2025 Ramon Santamaria (@raysan5) //\n");
  968. byteCount += sprintf(txtData + byteCount, "// //\n");
  969. byteCount += sprintf(txtData + byteCount, "//////////////////////////////////////////////////////////////////////////////////\n\n");
  970. // Get file name from path and convert variable name to uppercase
  971. char varFileName[256] = { 0 };
  972. strcpy(varFileName, GetFileNameWithoutExt(fileName));
  973. for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; }
  974. // Add wave information
  975. byteCount += sprintf(txtData + byteCount, "// Wave data information\n");
  976. byteCount += sprintf(txtData + byteCount, "#define %s_FRAME_COUNT %u\n", varFileName, wave.frameCount);
  977. byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_RATE %u\n", varFileName, wave.sampleRate);
  978. byteCount += sprintf(txtData + byteCount, "#define %s_SAMPLE_SIZE %u\n", varFileName, wave.sampleSize);
  979. byteCount += sprintf(txtData + byteCount, "#define %s_CHANNELS %u\n\n", varFileName, wave.channels);
  980. // Write wave data as an array of values
  981. // Wave data is exported as byte array for 8/16bit and float array for 32bit float data
  982. // NOTE: Frame data exported is channel-interlaced: frame01[sampleChannel1, sampleChannel2, ...], frame02[], frame03[]
  983. if (wave.sampleSize == 32)
  984. {
  985. byteCount += sprintf(txtData + byteCount, "static float %s_DATA[%i] = {\n", varFileName, waveDataSize/4);
  986. for (int i = 1; i < waveDataSize/4; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "%.4ff,\n " : "%.4ff, "), ((float *)wave.data)[i - 1]);
  987. byteCount += sprintf(txtData + byteCount, "%.4ff };\n", ((float *)wave.data)[waveDataSize/4 - 1]);
  988. }
  989. else
  990. {
  991. byteCount += sprintf(txtData + byteCount, "static unsigned char %s_DATA[%i] = { ", varFileName, waveDataSize);
  992. for (int i = 1; i < waveDataSize; i++) byteCount += sprintf(txtData + byteCount, ((i%TEXT_BYTES_PER_LINE == 0)? "0x%x,\n " : "0x%x, "), ((unsigned char *)wave.data)[i - 1]);
  993. byteCount += sprintf(txtData + byteCount, "0x%x };\n", ((unsigned char *)wave.data)[waveDataSize - 1]);
  994. }
  995. // NOTE: Text data length exported is determined by '\0' (NULL) character
  996. success = SaveFileText(fileName, txtData);
  997. RL_FREE(txtData);
  998. if (success != 0) TRACELOG(LOG_INFO, "FILEIO: [%s] Wave as code exported successfully", fileName);
  999. else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to export wave as code", fileName);
  1000. return success;
  1001. }
  1002. // Play a sound
  1003. void PlaySound(Sound sound)
  1004. {
  1005. PlayAudioBuffer(sound.stream.buffer);
  1006. }
  1007. // Pause a sound
  1008. void PauseSound(Sound sound)
  1009. {
  1010. PauseAudioBuffer(sound.stream.buffer);
  1011. }
  1012. // Resume a paused sound
  1013. void ResumeSound(Sound sound)
  1014. {
  1015. ResumeAudioBuffer(sound.stream.buffer);
  1016. }
  1017. // Stop reproducing a sound
  1018. void StopSound(Sound sound)
  1019. {
  1020. StopAudioBuffer(sound.stream.buffer);
  1021. }
  1022. // Check if a sound is playing
  1023. bool IsSoundPlaying(Sound sound)
  1024. {
  1025. bool result = false;
  1026. if (IsAudioBufferPlaying(sound.stream.buffer)) result = true;
  1027. return result;
  1028. }
  1029. // Set volume for a sound
  1030. void SetSoundVolume(Sound sound, float volume)
  1031. {
  1032. SetAudioBufferVolume(sound.stream.buffer, volume);
  1033. }
  1034. // Set pitch for a sound
  1035. void SetSoundPitch(Sound sound, float pitch)
  1036. {
  1037. SetAudioBufferPitch(sound.stream.buffer, pitch);
  1038. }
  1039. // Set pan for a sound
  1040. void SetSoundPan(Sound sound, float pan)
  1041. {
  1042. SetAudioBufferPan(sound.stream.buffer, pan);
  1043. }
  1044. // Convert wave data to desired format
  1045. void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
  1046. {
  1047. ma_format formatIn = ((wave->sampleSize == 8)? ma_format_u8 : ((wave->sampleSize == 16)? ma_format_s16 : ma_format_f32));
  1048. ma_format formatOut = ((sampleSize == 8)? ma_format_u8 : ((sampleSize == 16)? ma_format_s16 : ma_format_f32));
  1049. ma_uint32 frameCountIn = wave->frameCount;
  1050. ma_uint32 frameCount = (ma_uint32)ma_convert_frames(NULL, 0, formatOut, channels, sampleRate, NULL, frameCountIn, formatIn, wave->channels, wave->sampleRate);
  1051. if (frameCount == 0)
  1052. {
  1053. TRACELOG(LOG_WARNING, "WAVE: Failed to get frame count for format conversion");
  1054. return;
  1055. }
  1056. void *data = RL_MALLOC(frameCount*channels*(sampleSize/8));
  1057. frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate);
  1058. if (frameCount == 0)
  1059. {
  1060. RL_FREE(wave->data);
  1061. TRACELOG(LOG_WARNING, "WAVE: Failed format conversion");
  1062. return;
  1063. }
  1064. wave->frameCount = frameCount;
  1065. wave->sampleSize = sampleSize;
  1066. wave->sampleRate = sampleRate;
  1067. wave->channels = channels;
  1068. RL_FREE(wave->data);
  1069. wave->data = data;
  1070. }
  1071. // Copy a wave to a new wave
  1072. Wave WaveCopy(Wave wave)
  1073. {
  1074. Wave newWave = { 0 };
  1075. newWave.data = RL_MALLOC(wave.frameCount*wave.channels*wave.sampleSize/8);
  1076. if (newWave.data != NULL)
  1077. {
  1078. // NOTE: Size must be provided in bytes
  1079. memcpy(newWave.data, wave.data, wave.frameCount*wave.channels*wave.sampleSize/8);
  1080. newWave.frameCount = wave.frameCount;
  1081. newWave.sampleRate = wave.sampleRate;
  1082. newWave.sampleSize = wave.sampleSize;
  1083. newWave.channels = wave.channels;
  1084. }
  1085. return newWave;
  1086. }
  1087. // Crop a wave to defined frames range
  1088. // NOTE: Security check in case of out-of-range
  1089. void WaveCrop(Wave *wave, int initFrame, int finalFrame)
  1090. {
  1091. if ((initFrame >= 0) && (initFrame < finalFrame) && ((unsigned int)finalFrame <= wave->frameCount))
  1092. {
  1093. int frameCount = finalFrame - initFrame;
  1094. void *data = RL_MALLOC(frameCount*wave->channels*wave->sampleSize/8);
  1095. memcpy(data, (unsigned char *)wave->data + (initFrame*wave->channels*wave->sampleSize/8), frameCount*wave->channels*wave->sampleSize/8);
  1096. RL_FREE(wave->data);
  1097. wave->data = data;
  1098. wave->frameCount = (unsigned int)frameCount;
  1099. }
  1100. else TRACELOG(LOG_WARNING, "WAVE: Crop range out of bounds");
  1101. }
  1102. // Load samples data from wave as a floats array
  1103. // NOTE 1: Returned sample values are normalized to range [-1..1]
  1104. // NOTE 2: Sample data allocated should be freed with UnloadWaveSamples()
  1105. float *LoadWaveSamples(Wave wave)
  1106. {
  1107. float *samples = (float *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(float));
  1108. // NOTE: sampleCount is the total number of interlaced samples (including channels)
  1109. for (unsigned int i = 0; i < wave.frameCount*wave.channels; i++)
  1110. {
  1111. if (wave.sampleSize == 8) samples[i] = (float)(((unsigned char *)wave.data)[i] - 128)/128.0f;
  1112. else if (wave.sampleSize == 16) samples[i] = (float)(((short *)wave.data)[i])/32768.0f;
  1113. else if (wave.sampleSize == 32) samples[i] = ((float *)wave.data)[i];
  1114. }
  1115. return samples;
  1116. }
  1117. // Unload samples data loaded with LoadWaveSamples()
  1118. void UnloadWaveSamples(float *samples)
  1119. {
  1120. RL_FREE(samples);
  1121. }
  1122. //----------------------------------------------------------------------------------
  1123. // Module Functions Definition - Music loading and stream playing
  1124. //----------------------------------------------------------------------------------
  1125. // Load music stream from file
  1126. Music LoadMusicStream(const char *fileName)
  1127. {
  1128. Music music = { 0 };
  1129. bool musicLoaded = false;
  1130. if (false) { }
  1131. #if defined(SUPPORT_FILEFORMAT_WAV)
  1132. else if (IsFileExtension(fileName, ".wav"))
  1133. {
  1134. drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
  1135. bool success = drwav_init_file(ctxWav, fileName, NULL);
  1136. if (success)
  1137. {
  1138. music.ctxType = MUSIC_AUDIO_WAV;
  1139. music.ctxData = ctxWav;
  1140. int sampleSize = ctxWav->bitsPerSample;
  1141. if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
  1142. music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
  1143. music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount;
  1144. music.looping = true; // Looping enabled by default
  1145. musicLoaded = true;
  1146. }
  1147. else
  1148. {
  1149. RL_FREE(ctxWav);
  1150. }
  1151. }
  1152. #endif
  1153. #if defined(SUPPORT_FILEFORMAT_OGG)
  1154. else if (IsFileExtension(fileName, ".ogg"))
  1155. {
  1156. // Open ogg audio stream
  1157. stb_vorbis *ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL);
  1158. if (ctxOgg != NULL)
  1159. {
  1160. music.ctxType = MUSIC_AUDIO_OGG;
  1161. music.ctxData = ctxOgg;
  1162. stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData); // Get Ogg file info
  1163. // OGG bit rate defaults to 16 bit, it's enough for compressed format
  1164. music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
  1165. // WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
  1166. music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData);
  1167. music.looping = true; // Looping enabled by default
  1168. musicLoaded = true;
  1169. }
  1170. else
  1171. {
  1172. stb_vorbis_close(ctxOgg);
  1173. }
  1174. }
  1175. #endif
  1176. #if defined(SUPPORT_FILEFORMAT_MP3)
  1177. else if (IsFileExtension(fileName, ".mp3"))
  1178. {
  1179. drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
  1180. int result = drmp3_init_file(ctxMp3, fileName, NULL);
  1181. if (result > 0)
  1182. {
  1183. music.ctxType = MUSIC_AUDIO_MP3;
  1184. music.ctxData = ctxMp3;
  1185. music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
  1186. music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3);
  1187. music.looping = true; // Looping enabled by default
  1188. musicLoaded = true;
  1189. }
  1190. else
  1191. {
  1192. RL_FREE(ctxMp3);
  1193. }
  1194. }
  1195. #endif
  1196. #if defined(SUPPORT_FILEFORMAT_QOA)
  1197. else if (IsFileExtension(fileName, ".qoa"))
  1198. {
  1199. qoaplay_desc *ctxQoa = qoaplay_open(fileName);
  1200. if (ctxQoa != NULL)
  1201. {
  1202. music.ctxType = MUSIC_AUDIO_QOA;
  1203. music.ctxData = ctxQoa;
  1204. // NOTE: We are loading samples are 32bit float normalized data, so,
  1205. // we configure the output audio stream to also use float 32bit
  1206. music.stream = LoadAudioStream(ctxQoa->info.samplerate, 32, ctxQoa->info.channels);
  1207. music.frameCount = ctxQoa->info.samples;
  1208. music.looping = true; // Looping enabled by default
  1209. musicLoaded = true;
  1210. }
  1211. else{} //No uninit required
  1212. }
  1213. #endif
  1214. #if defined(SUPPORT_FILEFORMAT_FLAC)
  1215. else if (IsFileExtension(fileName, ".flac"))
  1216. {
  1217. drflac *ctxFlac = drflac_open_file(fileName, NULL);
  1218. if (ctxFlac != NULL)
  1219. {
  1220. music.ctxType = MUSIC_AUDIO_FLAC;
  1221. music.ctxData = ctxFlac;
  1222. int sampleSize = ctxFlac->bitsPerSample;
  1223. if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
  1224. music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, ctxFlac->channels);
  1225. music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
  1226. music.looping = true; // Looping enabled by default
  1227. musicLoaded = true;
  1228. }
  1229. else
  1230. {
  1231. drflac_free(ctxFlac, NULL);
  1232. }
  1233. }
  1234. #endif
  1235. #if defined(SUPPORT_FILEFORMAT_XM)
  1236. else if (IsFileExtension(fileName, ".xm"))
  1237. {
  1238. jar_xm_context_t *ctxXm = NULL;
  1239. int result = jar_xm_create_context_from_file(&ctxXm, AUDIO.System.device.sampleRate, fileName);
  1240. if (result == 0) // XM AUDIO.System.context created successfully
  1241. {
  1242. music.ctxType = MUSIC_MODULE_XM;
  1243. music.ctxData = ctxXm;
  1244. jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops
  1245. unsigned int bits = 32;
  1246. if (AUDIO_DEVICE_FORMAT == ma_format_s16) bits = 16;
  1247. else if (AUDIO_DEVICE_FORMAT == ma_format_u8) bits = 8;
  1248. // NOTE: Only stereo is supported for XM
  1249. music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, AUDIO_DEVICE_CHANNELS);
  1250. music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo)
  1251. music.looping = true; // Looping enabled by default
  1252. jar_xm_reset(ctxXm); // Make sure we start at the beginning of the song
  1253. musicLoaded = true;
  1254. }
  1255. else
  1256. {
  1257. jar_xm_free_context(ctxXm);
  1258. }
  1259. }
  1260. #endif
  1261. #if defined(SUPPORT_FILEFORMAT_MOD)
  1262. else if (IsFileExtension(fileName, ".mod"))
  1263. {
  1264. jar_mod_context_t *ctxMod = (jar_mod_context_t *)RL_CALLOC(1, sizeof(jar_mod_context_t));
  1265. jar_mod_init(ctxMod);
  1266. int result = jar_mod_load_file(ctxMod, fileName);
  1267. if (result > 0)
  1268. {
  1269. music.ctxType = MUSIC_MODULE_MOD;
  1270. music.ctxData = ctxMod;
  1271. // NOTE: Only stereo is supported for MOD
  1272. music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, AUDIO_DEVICE_CHANNELS);
  1273. music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo)
  1274. music.looping = true; // Looping enabled by default
  1275. musicLoaded = true;
  1276. }
  1277. else
  1278. {
  1279. jar_mod_unload(ctxMod);
  1280. RL_FREE(ctxMod);
  1281. }
  1282. }
  1283. #endif
  1284. else TRACELOG(LOG_WARNING, "STREAM: [%s] File format not supported", fileName);
  1285. if (!musicLoaded)
  1286. {
  1287. TRACELOG(LOG_WARNING, "FILEIO: [%s] Music file could not be opened", fileName);
  1288. }
  1289. else
  1290. {
  1291. // Show some music stream info
  1292. TRACELOG(LOG_INFO, "FILEIO: [%s] Music file loaded successfully", fileName);
  1293. TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate);
  1294. TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize);
  1295. TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi");
  1296. TRACELOG(LOG_INFO, " > Total frames: %i", music.frameCount);
  1297. }
  1298. return music;
  1299. }
  1300. // Load music stream from memory buffer, fileType refers to extension: i.e. ".wav"
  1301. // WARNING: File extension must be provided in lower-case
  1302. Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize)
  1303. {
  1304. Music music = { 0 };
  1305. bool musicLoaded = false;
  1306. if (false) { }
  1307. #if defined(SUPPORT_FILEFORMAT_WAV)
  1308. else if ((strcmp(fileType, ".wav") == 0) || (strcmp(fileType, ".WAV") == 0))
  1309. {
  1310. drwav *ctxWav = (drwav *)RL_CALLOC(1, sizeof(drwav));
  1311. bool success = drwav_init_memory(ctxWav, (const void *)data, dataSize, NULL);
  1312. if (success)
  1313. {
  1314. music.ctxType = MUSIC_AUDIO_WAV;
  1315. music.ctxData = ctxWav;
  1316. int sampleSize = ctxWav->bitsPerSample;
  1317. if (ctxWav->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
  1318. music.stream = LoadAudioStream(ctxWav->sampleRate, sampleSize, ctxWav->channels);
  1319. music.frameCount = (unsigned int)ctxWav->totalPCMFrameCount;
  1320. music.looping = true; // Looping enabled by default
  1321. musicLoaded = true;
  1322. }
  1323. else
  1324. {
  1325. drwav_uninit(ctxWav);
  1326. RL_FREE(ctxWav);
  1327. }
  1328. }
  1329. #endif
  1330. #if defined(SUPPORT_FILEFORMAT_OGG)
  1331. else if ((strcmp(fileType, ".ogg") == 0) || (strcmp(fileType, ".OGG") == 0))
  1332. {
  1333. // Open ogg audio stream
  1334. stb_vorbis *ctxOgg = stb_vorbis_open_memory((const unsigned char *)data, dataSize, NULL, NULL);
  1335. if (ctxOgg != NULL)
  1336. {
  1337. music.ctxType = MUSIC_AUDIO_OGG;
  1338. music.ctxData = ctxOgg;
  1339. stb_vorbis_info info = stb_vorbis_get_info((stb_vorbis *)music.ctxData); // Get Ogg file info
  1340. // OGG bit rate defaults to 16 bit, it's enough for compressed format
  1341. music.stream = LoadAudioStream(info.sample_rate, 16, info.channels);
  1342. // WARNING: It seems this function returns length in frames, not samples, so we multiply by channels
  1343. music.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples((stb_vorbis *)music.ctxData);
  1344. music.looping = true; // Looping enabled by default
  1345. musicLoaded = true;
  1346. }
  1347. else
  1348. {
  1349. stb_vorbis_close(ctxOgg);
  1350. }
  1351. }
  1352. #endif
  1353. #if defined(SUPPORT_FILEFORMAT_MP3)
  1354. else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
  1355. {
  1356. drmp3 *ctxMp3 = (drmp3 *)RL_CALLOC(1, sizeof(drmp3));
  1357. int success = drmp3_init_memory(ctxMp3, (const void*)data, dataSize, NULL);
  1358. if (success)
  1359. {
  1360. music.ctxType = MUSIC_AUDIO_MP3;
  1361. music.ctxData = ctxMp3;
  1362. music.stream = LoadAudioStream(ctxMp3->sampleRate, 32, ctxMp3->channels);
  1363. music.frameCount = (unsigned int)drmp3_get_pcm_frame_count(ctxMp3);
  1364. music.looping = true; // Looping enabled by default
  1365. musicLoaded = true;
  1366. }
  1367. else
  1368. {
  1369. drmp3_uninit(ctxMp3);
  1370. RL_FREE(ctxMp3);
  1371. }
  1372. }
  1373. #endif
  1374. #if defined(SUPPORT_FILEFORMAT_QOA)
  1375. else if ((strcmp(fileType, ".qoa") == 0) || (strcmp(fileType, ".QOA") == 0))
  1376. {
  1377. qoaplay_desc *ctxQoa = NULL;
  1378. if ((data != NULL) && (dataSize > 0))
  1379. {
  1380. ctxQoa = qoaplay_open_memory(data, dataSize);
  1381. }
  1382. if (ctxQoa != NULL)
  1383. {
  1384. music.ctxType = MUSIC_AUDIO_QOA;
  1385. music.ctxData = ctxQoa;
  1386. // NOTE: We are loading samples are 32bit float normalized data, so,
  1387. // we configure the output audio stream to also use float 32bit
  1388. music.stream = LoadAudioStream(ctxQoa->info.samplerate, 32, ctxQoa->info.channels);
  1389. music.frameCount = ctxQoa->info.samples;
  1390. music.looping = true; // Looping enabled by default
  1391. musicLoaded = true;
  1392. }
  1393. else{} //No uninit required
  1394. }
  1395. #endif
  1396. #if defined(SUPPORT_FILEFORMAT_FLAC)
  1397. else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
  1398. {
  1399. drflac *ctxFlac = drflac_open_memory((const void*)data, dataSize, NULL);
  1400. if (ctxFlac != NULL)
  1401. {
  1402. music.ctxType = MUSIC_AUDIO_FLAC;
  1403. music.ctxData = ctxFlac;
  1404. int sampleSize = ctxFlac->bitsPerSample;
  1405. if (ctxFlac->bitsPerSample == 24) sampleSize = 16; // Forcing conversion to s16 on UpdateMusicStream()
  1406. music.stream = LoadAudioStream(ctxFlac->sampleRate, sampleSize, ctxFlac->channels);
  1407. music.frameCount = (unsigned int)ctxFlac->totalPCMFrameCount;
  1408. music.looping = true; // Looping enabled by default
  1409. musicLoaded = true;
  1410. }
  1411. else
  1412. {
  1413. drflac_free(ctxFlac, NULL);
  1414. }
  1415. }
  1416. #endif
  1417. #if defined(SUPPORT_FILEFORMAT_XM)
  1418. else if ((strcmp(fileType, ".xm") == 0) || (strcmp(fileType, ".XM") == 0))
  1419. {
  1420. jar_xm_context_t *ctxXm = NULL;
  1421. int result = jar_xm_create_context_safe(&ctxXm, (const char *)data, dataSize, AUDIO.System.device.sampleRate);
  1422. if (result == 0) // XM AUDIO.System.context created successfully
  1423. {
  1424. music.ctxType = MUSIC_MODULE_XM;
  1425. music.ctxData = ctxXm;
  1426. jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops
  1427. unsigned int bits = 32;
  1428. if (AUDIO_DEVICE_FORMAT == ma_format_s16) bits = 16;
  1429. else if (AUDIO_DEVICE_FORMAT == ma_format_u8) bits = 8;
  1430. // NOTE: Only stereo is supported for XM
  1431. music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, bits, 2);
  1432. music.frameCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm); // NOTE: Always 2 channels (stereo)
  1433. music.looping = true; // Looping enabled by default
  1434. jar_xm_reset(ctxXm); // Make sure we start at the beginning of the song
  1435. musicLoaded = true;
  1436. }
  1437. else
  1438. {
  1439. jar_xm_free_context(ctxXm);
  1440. }
  1441. }
  1442. #endif
  1443. #if defined(SUPPORT_FILEFORMAT_MOD)
  1444. else if ((strcmp(fileType, ".mod") == 0) || (strcmp(fileType, ".MOD") == 0))
  1445. {
  1446. jar_mod_context_t *ctxMod = (jar_mod_context_t *)RL_MALLOC(sizeof(jar_mod_context_t));
  1447. int result = 0;
  1448. jar_mod_init(ctxMod);
  1449. // Copy data to allocated memory for default UnloadMusicStream
  1450. unsigned char *newData = (unsigned char *)RL_MALLOC(dataSize);
  1451. int it = dataSize/sizeof(unsigned char);
  1452. for (int i = 0; i < it; i++) newData[i] = data[i];
  1453. // Memory loaded version for jar_mod_load_file()
  1454. if (dataSize && (dataSize < 32*1024*1024))
  1455. {
  1456. ctxMod->modfilesize = dataSize;
  1457. ctxMod->modfile = newData;
  1458. if (jar_mod_load(ctxMod, (void *)ctxMod->modfile, dataSize)) result = dataSize;
  1459. }
  1460. if (result > 0)
  1461. {
  1462. music.ctxType = MUSIC_MODULE_MOD;
  1463. music.ctxData = ctxMod;
  1464. // NOTE: Only stereo is supported for MOD
  1465. music.stream = LoadAudioStream(AUDIO.System.device.sampleRate, 16, 2);
  1466. music.frameCount = (unsigned int)jar_mod_max_samples(ctxMod); // NOTE: Always 2 channels (stereo)
  1467. music.looping = true; // Looping enabled by default
  1468. musicLoaded = true;
  1469. }
  1470. else
  1471. {
  1472. jar_mod_unload(ctxMod);
  1473. RL_FREE(ctxMod);
  1474. }
  1475. }
  1476. #endif
  1477. else TRACELOG(LOG_WARNING, "STREAM: Data format not supported");
  1478. if (!musicLoaded)
  1479. {
  1480. TRACELOG(LOG_WARNING, "FILEIO: Music data could not be loaded");
  1481. }
  1482. else
  1483. {
  1484. // Show some music stream info
  1485. TRACELOG(LOG_INFO, "FILEIO: Music data loaded successfully");
  1486. TRACELOG(LOG_INFO, " > Sample rate: %i Hz", music.stream.sampleRate);
  1487. TRACELOG(LOG_INFO, " > Sample size: %i bits", music.stream.sampleSize);
  1488. TRACELOG(LOG_INFO, " > Channels: %i (%s)", music.stream.channels, (music.stream.channels == 1)? "Mono" : (music.stream.channels == 2)? "Stereo" : "Multi");
  1489. TRACELOG(LOG_INFO, " > Total frames: %i", music.frameCount);
  1490. }
  1491. return music;
  1492. }
  1493. // Checks if a music stream is valid (context and buffers initialized)
  1494. bool IsMusicValid(Music music)
  1495. {
  1496. return ((music.ctxData != NULL) && // Validate context loaded
  1497. (music.frameCount > 0) && // Validate audio frame count
  1498. (music.stream.sampleRate > 0) && // Validate sample rate is supported
  1499. (music.stream.sampleSize > 0) && // Validate sample size is supported
  1500. (music.stream.channels > 0)); // Validate number of channels supported
  1501. }
  1502. // Unload music stream
  1503. void UnloadMusicStream(Music music)
  1504. {
  1505. UnloadAudioStream(music.stream);
  1506. if (music.ctxData != NULL)
  1507. {
  1508. if (false) { }
  1509. #if defined(SUPPORT_FILEFORMAT_WAV)
  1510. else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData);
  1511. #endif
  1512. #if defined(SUPPORT_FILEFORMAT_OGG)
  1513. else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
  1514. #endif
  1515. #if defined(SUPPORT_FILEFORMAT_MP3)
  1516. else if (music.ctxType == MUSIC_AUDIO_MP3) { drmp3_uninit((drmp3 *)music.ctxData); RL_FREE(music.ctxData); }
  1517. #endif
  1518. #if defined(SUPPORT_FILEFORMAT_QOA)
  1519. else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData);
  1520. #endif
  1521. #if defined(SUPPORT_FILEFORMAT_FLAC)
  1522. else if (music.ctxType == MUSIC_AUDIO_FLAC) { drflac_close((drflac *)music.ctxData); drflac_free((drflac *)music.ctxData, NULL); }
  1523. #endif
  1524. #if defined(SUPPORT_FILEFORMAT_XM)
  1525. else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);
  1526. #endif
  1527. #if defined(SUPPORT_FILEFORMAT_MOD)
  1528. else if (music.ctxType == MUSIC_MODULE_MOD) { jar_mod_unload((jar_mod_context_t *)music.ctxData); RL_FREE(music.ctxData); }
  1529. #endif
  1530. }
  1531. }
  1532. // Start music playing (open stream) from beginning
  1533. void PlayMusicStream(Music music)
  1534. {
  1535. PlayAudioStream(music.stream);
  1536. }
  1537. // Pause music playing
  1538. void PauseMusicStream(Music music)
  1539. {
  1540. PauseAudioStream(music.stream);
  1541. }
  1542. // Resume music playing
  1543. void ResumeMusicStream(Music music)
  1544. {
  1545. ResumeAudioStream(music.stream);
  1546. }
  1547. // Stop music playing (close stream)
  1548. void StopMusicStream(Music music)
  1549. {
  1550. StopAudioStream(music.stream);
  1551. switch (music.ctxType)
  1552. {
  1553. #if defined(SUPPORT_FILEFORMAT_WAV)
  1554. case MUSIC_AUDIO_WAV: drwav_seek_to_first_pcm_frame((drwav *)music.ctxData); break;
  1555. #endif
  1556. #if defined(SUPPORT_FILEFORMAT_OGG)
  1557. case MUSIC_AUDIO_OGG: stb_vorbis_seek_start((stb_vorbis *)music.ctxData); break;
  1558. #endif
  1559. #if defined(SUPPORT_FILEFORMAT_MP3)
  1560. case MUSIC_AUDIO_MP3: drmp3_seek_to_start_of_stream((drmp3 *)music.ctxData); break;
  1561. #endif
  1562. #if defined(SUPPORT_FILEFORMAT_QOA)
  1563. case MUSIC_AUDIO_QOA: qoaplay_rewind((qoaplay_desc *)music.ctxData); break;
  1564. #endif
  1565. #if defined(SUPPORT_FILEFORMAT_FLAC)
  1566. case MUSIC_AUDIO_FLAC: drflac__seek_to_first_frame((drflac *)music.ctxData); break;
  1567. #endif
  1568. #if defined(SUPPORT_FILEFORMAT_XM)
  1569. case MUSIC_MODULE_XM: jar_xm_reset((jar_xm_context_t *)music.ctxData); break;
  1570. #endif
  1571. #if defined(SUPPORT_FILEFORMAT_MOD)
  1572. case MUSIC_MODULE_MOD: jar_mod_seek_start((jar_mod_context_t *)music.ctxData); break;
  1573. #endif
  1574. default: break;
  1575. }
  1576. }
  1577. // Seek music to a certain position (in seconds)
  1578. void SeekMusicStream(Music music, float position)
  1579. {
  1580. // Seeking is not supported in module formats
  1581. if ((music.ctxType == MUSIC_MODULE_XM) || (music.ctxType == MUSIC_MODULE_MOD)) return;
  1582. unsigned int positionInFrames = (unsigned int)(position*music.stream.sampleRate);
  1583. switch (music.ctxType)
  1584. {
  1585. #if defined(SUPPORT_FILEFORMAT_WAV)
  1586. case MUSIC_AUDIO_WAV: drwav_seek_to_pcm_frame((drwav *)music.ctxData, positionInFrames); break;
  1587. #endif
  1588. #if defined(SUPPORT_FILEFORMAT_OGG)
  1589. case MUSIC_AUDIO_OGG: stb_vorbis_seek_frame((stb_vorbis *)music.ctxData, positionInFrames); break;
  1590. #endif
  1591. #if defined(SUPPORT_FILEFORMAT_MP3)
  1592. case MUSIC_AUDIO_MP3: drmp3_seek_to_pcm_frame((drmp3 *)music.ctxData, positionInFrames); break;
  1593. #endif
  1594. #if defined(SUPPORT_FILEFORMAT_QOA)
  1595. case MUSIC_AUDIO_QOA:
  1596. {
  1597. int qoaFrame = positionInFrames/QOA_FRAME_LEN;
  1598. qoaplay_seek_frame((qoaplay_desc *)music.ctxData, qoaFrame); // Seeks to QOA frame, not PCM frame
  1599. // We need to compute QOA frame number and update positionInFrames
  1600. positionInFrames = ((qoaplay_desc *)music.ctxData)->sample_position;
  1601. } break;
  1602. #endif
  1603. #if defined(SUPPORT_FILEFORMAT_FLAC)
  1604. case MUSIC_AUDIO_FLAC: drflac_seek_to_pcm_frame((drflac *)music.ctxData, positionInFrames); break;
  1605. #endif
  1606. default: break;
  1607. }
  1608. ma_mutex_lock(&AUDIO.System.lock);
  1609. music.stream.buffer->framesProcessed = positionInFrames;
  1610. music.stream.buffer->isSubBufferProcessed[0] = true;
  1611. music.stream.buffer->isSubBufferProcessed[1] = true;
  1612. ma_mutex_unlock(&AUDIO.System.lock);
  1613. }
  1614. // Update (re-fill) music buffers if data already processed
  1615. void UpdateMusicStream(Music music)
  1616. {
  1617. if (music.stream.buffer == NULL) return;
  1618. if (!music.stream.buffer->playing) return;
  1619. ma_mutex_lock(&AUDIO.System.lock);
  1620. unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2;
  1621. // On first call of this function we lazily pre-allocated a temp buffer to read audio files/memory data in
  1622. int frameSize = music.stream.channels*music.stream.sampleSize/8;
  1623. unsigned int pcmSize = subBufferSizeInFrames*frameSize;
  1624. if (AUDIO.System.pcmBufferSize < pcmSize)
  1625. {
  1626. RL_FREE(AUDIO.System.pcmBuffer);
  1627. AUDIO.System.pcmBuffer = RL_CALLOC(1, pcmSize);
  1628. AUDIO.System.pcmBufferSize = pcmSize;
  1629. }
  1630. // Check both sub-buffers to check if they require refilling
  1631. for (int i = 0; i < 2; i++)
  1632. {
  1633. unsigned int framesLeft = music.frameCount - music.stream.buffer->framesProcessed; // Frames left to be processed
  1634. unsigned int framesToStream = 0; // Total frames to be streamed
  1635. if ((framesLeft >= subBufferSizeInFrames) || music.looping) framesToStream = subBufferSizeInFrames;
  1636. else framesToStream = framesLeft;
  1637. if (framesToStream == 0)
  1638. {
  1639. // Check if both buffers have been processed
  1640. if (music.stream.buffer->isSubBufferProcessed[0] && music.stream.buffer->isSubBufferProcessed[1])
  1641. {
  1642. ma_mutex_unlock(&AUDIO.System.lock);
  1643. StopMusicStream(music);
  1644. return;
  1645. }
  1646. ma_mutex_unlock(&AUDIO.System.lock);
  1647. return;
  1648. }
  1649. if (!music.stream.buffer->isSubBufferProcessed[i]) continue; // No refilling required, move to next sub-buffer
  1650. int frameCountStillNeeded = framesToStream;
  1651. int frameCountReadTotal = 0;
  1652. switch (music.ctxType)
  1653. {
  1654. #if defined(SUPPORT_FILEFORMAT_WAV)
  1655. case MUSIC_AUDIO_WAV:
  1656. {
  1657. if (music.stream.sampleSize == 16)
  1658. {
  1659. while (true)
  1660. {
  1661. int frameCountRead = (int)drwav_read_pcm_frames_s16((drwav *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
  1662. frameCountReadTotal += frameCountRead;
  1663. frameCountStillNeeded -= frameCountRead;
  1664. if (frameCountStillNeeded == 0) break;
  1665. else drwav_seek_to_first_pcm_frame((drwav *)music.ctxData);
  1666. }
  1667. }
  1668. else if (music.stream.sampleSize == 32)
  1669. {
  1670. while (true)
  1671. {
  1672. int frameCountRead = (int)drwav_read_pcm_frames_f32((drwav *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
  1673. frameCountReadTotal += frameCountRead;
  1674. frameCountStillNeeded -= frameCountRead;
  1675. if (frameCountStillNeeded == 0) break;
  1676. else drwav_seek_to_first_pcm_frame((drwav *)music.ctxData);
  1677. }
  1678. }
  1679. } break;
  1680. #endif
  1681. #if defined(SUPPORT_FILEFORMAT_OGG)
  1682. case MUSIC_AUDIO_OGG:
  1683. {
  1684. while (true)
  1685. {
  1686. int frameCountRead = stb_vorbis_get_samples_short_interleaved((stb_vorbis *)music.ctxData, music.stream.channels, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize), frameCountStillNeeded*music.stream.channels);
  1687. frameCountReadTotal += frameCountRead;
  1688. frameCountStillNeeded -= frameCountRead;
  1689. if (frameCountStillNeeded == 0) break;
  1690. else stb_vorbis_seek_start((stb_vorbis *)music.ctxData);
  1691. }
  1692. } break;
  1693. #endif
  1694. #if defined(SUPPORT_FILEFORMAT_MP3)
  1695. case MUSIC_AUDIO_MP3:
  1696. {
  1697. while (true)
  1698. {
  1699. int frameCountRead = (int)drmp3_read_pcm_frames_f32((drmp3 *)music.ctxData, frameCountStillNeeded, (float *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
  1700. frameCountReadTotal += frameCountRead;
  1701. frameCountStillNeeded -= frameCountRead;
  1702. if (frameCountStillNeeded == 0) break;
  1703. else drmp3_seek_to_start_of_stream((drmp3 *)music.ctxData);
  1704. }
  1705. } break;
  1706. #endif
  1707. #if defined(SUPPORT_FILEFORMAT_QOA)
  1708. case MUSIC_AUDIO_QOA:
  1709. {
  1710. unsigned int frameCountRead = qoaplay_decode((qoaplay_desc *)music.ctxData, (float *)AUDIO.System.pcmBuffer, framesToStream);
  1711. frameCountReadTotal += frameCountRead;
  1712. /*
  1713. while (true)
  1714. {
  1715. int frameCountRead = (int)qoaplay_decode((qoaplay_desc *)music.ctxData, (float *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize), frameCountStillNeeded);
  1716. frameCountReadTotal += frameCountRead;
  1717. frameCountStillNeeded -= frameCountRead;
  1718. if (frameCountStillNeeded == 0) break;
  1719. else qoaplay_rewind((qoaplay_desc *)music.ctxData);
  1720. }
  1721. */
  1722. } break;
  1723. #endif
  1724. #if defined(SUPPORT_FILEFORMAT_FLAC)
  1725. case MUSIC_AUDIO_FLAC:
  1726. {
  1727. while (true)
  1728. {
  1729. int frameCountRead = (int)drflac_read_pcm_frames_s16((drflac *)music.ctxData, frameCountStillNeeded, (short *)((char *)AUDIO.System.pcmBuffer + frameCountReadTotal*frameSize));
  1730. frameCountReadTotal += frameCountRead;
  1731. frameCountStillNeeded -= frameCountRead;
  1732. if (frameCountStillNeeded == 0) break;
  1733. else drflac__seek_to_first_frame((drflac *)music.ctxData);
  1734. }
  1735. } break;
  1736. #endif
  1737. #if defined(SUPPORT_FILEFORMAT_XM)
  1738. case MUSIC_MODULE_XM:
  1739. {
  1740. // NOTE: Internally we consider 2 channels generation, so sampleCount/2
  1741. if (AUDIO_DEVICE_FORMAT == ma_format_f32) jar_xm_generate_samples((jar_xm_context_t *)music.ctxData, (float *)AUDIO.System.pcmBuffer, framesToStream);
  1742. else if (AUDIO_DEVICE_FORMAT == ma_format_s16) jar_xm_generate_samples_16bit((jar_xm_context_t *)music.ctxData, (short *)AUDIO.System.pcmBuffer, framesToStream);
  1743. else if (AUDIO_DEVICE_FORMAT == ma_format_u8) jar_xm_generate_samples_8bit((jar_xm_context_t *)music.ctxData, (char *)AUDIO.System.pcmBuffer, framesToStream);
  1744. //jar_xm_reset((jar_xm_context_t *)music.ctxData);
  1745. } break;
  1746. #endif
  1747. #if defined(SUPPORT_FILEFORMAT_MOD)
  1748. case MUSIC_MODULE_MOD:
  1749. {
  1750. // NOTE: 3rd parameter (nbsample) specify the number of stereo 16bits samples you want, so sampleCount/2
  1751. jar_mod_fillbuffer((jar_mod_context_t *)music.ctxData, (short *)AUDIO.System.pcmBuffer, framesToStream, 0);
  1752. //jar_mod_seek_start((jar_mod_context_t *)music.ctxData);
  1753. } break;
  1754. #endif
  1755. default: break;
  1756. }
  1757. UpdateAudioStreamInLockedState(music.stream, AUDIO.System.pcmBuffer, framesToStream);
  1758. }
  1759. ma_mutex_unlock(&AUDIO.System.lock);
  1760. }
  1761. // Check if any music is playing
  1762. bool IsMusicStreamPlaying(Music music)
  1763. {
  1764. return IsAudioStreamPlaying(music.stream);
  1765. }
  1766. // Set volume for music
  1767. void SetMusicVolume(Music music, float volume)
  1768. {
  1769. SetAudioStreamVolume(music.stream, volume);
  1770. }
  1771. // Set pitch for music
  1772. void SetMusicPitch(Music music, float pitch)
  1773. {
  1774. SetAudioBufferPitch(music.stream.buffer, pitch);
  1775. }
  1776. // Set pan for a music
  1777. void SetMusicPan(Music music, float pan)
  1778. {
  1779. SetAudioBufferPan(music.stream.buffer, pan);
  1780. }
  1781. // Get music time length (in seconds)
  1782. float GetMusicTimeLength(Music music)
  1783. {
  1784. float totalSeconds = 0.0f;
  1785. totalSeconds = (float)music.frameCount/music.stream.sampleRate;
  1786. return totalSeconds;
  1787. }
  1788. // Get current music time played (in seconds)
  1789. float GetMusicTimePlayed(Music music)
  1790. {
  1791. float secondsPlayed = 0.0f;
  1792. if (music.stream.buffer != NULL)
  1793. {
  1794. #if defined(SUPPORT_FILEFORMAT_XM)
  1795. if (music.ctxType == MUSIC_MODULE_XM)
  1796. {
  1797. uint64_t framesPlayed = 0;
  1798. jar_xm_get_position(music.ctxData, NULL, NULL, NULL, &framesPlayed);
  1799. secondsPlayed = (float)framesPlayed/music.stream.sampleRate;
  1800. }
  1801. else
  1802. #endif
  1803. {
  1804. ma_mutex_lock(&AUDIO.System.lock);
  1805. //ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
  1806. int framesProcessed = (int)music.stream.buffer->framesProcessed;
  1807. int subBufferSize = (int)music.stream.buffer->sizeInFrames/2;
  1808. int framesInFirstBuffer = music.stream.buffer->isSubBufferProcessed[0]? 0 : subBufferSize;
  1809. int framesInSecondBuffer = music.stream.buffer->isSubBufferProcessed[1]? 0 : subBufferSize;
  1810. int framesInBuffers = framesInFirstBuffer + framesInSecondBuffer;
  1811. if ((unsigned int)framesInBuffers > music.frameCount) {
  1812. if (!music.looping) framesInBuffers = music.frameCount;
  1813. }
  1814. int framesSentToMix = music.stream.buffer->frameCursorPos%subBufferSize;
  1815. int framesPlayed = (framesProcessed - framesInBuffers + framesSentToMix)%(int)music.frameCount;
  1816. if (framesPlayed < 0) framesPlayed += music.frameCount;
  1817. secondsPlayed = (float)framesPlayed/music.stream.sampleRate;
  1818. ma_mutex_unlock(&AUDIO.System.lock);
  1819. }
  1820. }
  1821. return secondsPlayed;
  1822. }
  1823. // Load audio stream (to stream audio pcm data)
  1824. AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels)
  1825. {
  1826. AudioStream stream = { 0 };
  1827. stream.sampleRate = sampleRate;
  1828. stream.sampleSize = sampleSize;
  1829. stream.channels = channels;
  1830. ma_format formatIn = ((stream.sampleSize == 8)? ma_format_u8 : ((stream.sampleSize == 16)? ma_format_s16 : ma_format_f32));
  1831. // The size of a streaming buffer must be at least double the size of a period
  1832. unsigned int periodSize = AUDIO.System.device.playback.internalPeriodSizeInFrames;
  1833. // If the buffer is not set, compute one that would give us a buffer good enough for a decent frame rate at the device bit size/rate
  1834. int deviceBitsPerSample = AUDIO.System.device.playback.format;
  1835. if (deviceBitsPerSample > 4) deviceBitsPerSample = 4;
  1836. deviceBitsPerSample *= AUDIO.System.device.playback.channels;
  1837. unsigned int subBufferSize = (AUDIO.Buffer.defaultSize == 0) ? (AUDIO.System.device.sampleRate/30*deviceBitsPerSample) : AUDIO.Buffer.defaultSize;
  1838. if (subBufferSize < periodSize) subBufferSize = periodSize;
  1839. // Create a double audio buffer of defined size
  1840. stream.buffer = LoadAudioBuffer(formatIn, stream.channels, stream.sampleRate, subBufferSize*2, AUDIO_BUFFER_USAGE_STREAM);
  1841. if (stream.buffer != NULL)
  1842. {
  1843. stream.buffer->looping = true; // Always loop for streaming buffers
  1844. TRACELOG(LOG_INFO, "STREAM: Initialized successfully (%i Hz, %i bit, %s)", stream.sampleRate, stream.sampleSize, (stream.channels == 1)? "Mono" : "Stereo");
  1845. }
  1846. else TRACELOG(LOG_WARNING, "STREAM: Failed to load audio buffer, stream could not be created");
  1847. return stream;
  1848. }
  1849. // Checks if an audio stream is valid (buffers initialized)
  1850. bool IsAudioStreamValid(AudioStream stream)
  1851. {
  1852. return ((stream.buffer != NULL) && // Validate stream buffer
  1853. (stream.sampleRate > 0) && // Validate sample rate is supported
  1854. (stream.sampleSize > 0) && // Validate sample size is supported
  1855. (stream.channels > 0)); // Validate number of channels supported
  1856. }
  1857. // Unload audio stream and free memory
  1858. void UnloadAudioStream(AudioStream stream)
  1859. {
  1860. UnloadAudioBuffer(stream.buffer);
  1861. TRACELOG(LOG_INFO, "STREAM: Unloaded audio stream data from RAM");
  1862. }
  1863. // Update audio stream buffers with data
  1864. // NOTE 1: Only updates one buffer of the stream source: dequeue -> update -> queue
  1865. // NOTE 2: To dequeue a buffer it needs to be processed: IsAudioStreamProcessed()
  1866. void UpdateAudioStream(AudioStream stream, const void *data, int frameCount)
  1867. {
  1868. ma_mutex_lock(&AUDIO.System.lock);
  1869. UpdateAudioStreamInLockedState(stream, data, frameCount);
  1870. ma_mutex_unlock(&AUDIO.System.lock);
  1871. }
  1872. // Check if any audio stream buffers requires refill
  1873. bool IsAudioStreamProcessed(AudioStream stream)
  1874. {
  1875. if (stream.buffer == NULL) return false;
  1876. bool result = false;
  1877. ma_mutex_lock(&AUDIO.System.lock);
  1878. result = stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1];
  1879. ma_mutex_unlock(&AUDIO.System.lock);
  1880. return result;
  1881. }
  1882. // Play audio stream
  1883. void PlayAudioStream(AudioStream stream)
  1884. {
  1885. PlayAudioBuffer(stream.buffer);
  1886. }
  1887. // Play audio stream
  1888. void PauseAudioStream(AudioStream stream)
  1889. {
  1890. PauseAudioBuffer(stream.buffer);
  1891. }
  1892. // Resume audio stream playing
  1893. void ResumeAudioStream(AudioStream stream)
  1894. {
  1895. ResumeAudioBuffer(stream.buffer);
  1896. }
  1897. // Check if audio stream is playing
  1898. bool IsAudioStreamPlaying(AudioStream stream)
  1899. {
  1900. return IsAudioBufferPlaying(stream.buffer);
  1901. }
  1902. // Stop audio stream
  1903. void StopAudioStream(AudioStream stream)
  1904. {
  1905. StopAudioBuffer(stream.buffer);
  1906. }
  1907. // Set volume for audio stream (1.0 is max level)
  1908. void SetAudioStreamVolume(AudioStream stream, float volume)
  1909. {
  1910. SetAudioBufferVolume(stream.buffer, volume);
  1911. }
  1912. // Set pitch for audio stream (1.0 is base level)
  1913. void SetAudioStreamPitch(AudioStream stream, float pitch)
  1914. {
  1915. SetAudioBufferPitch(stream.buffer, pitch);
  1916. }
  1917. // Set pan for audio stream
  1918. void SetAudioStreamPan(AudioStream stream, float pan)
  1919. {
  1920. SetAudioBufferPan(stream.buffer, pan);
  1921. }
  1922. // Default size for new audio streams
  1923. void SetAudioStreamBufferSizeDefault(int size)
  1924. {
  1925. AUDIO.Buffer.defaultSize = size;
  1926. }
  1927. // Audio thread callback to request new data
  1928. void SetAudioStreamCallback(AudioStream stream, AudioCallback callback)
  1929. {
  1930. if (stream.buffer != NULL)
  1931. {
  1932. ma_mutex_lock(&AUDIO.System.lock);
  1933. stream.buffer->callback = callback;
  1934. ma_mutex_unlock(&AUDIO.System.lock);
  1935. }
  1936. }
  1937. // Add processor to audio stream. Contrary to buffers, the order of processors is important
  1938. // The new processor must be added at the end. As there aren't supposed to be a lot of processors attached to
  1939. // a given stream, we iterate through the list to find the end. That way we don't need a pointer to the last element
  1940. void AttachAudioStreamProcessor(AudioStream stream, AudioCallback process)
  1941. {
  1942. ma_mutex_lock(&AUDIO.System.lock);
  1943. rAudioProcessor *processor = (rAudioProcessor *)RL_CALLOC(1, sizeof(rAudioProcessor));
  1944. processor->process = process;
  1945. rAudioProcessor *last = stream.buffer->processor;
  1946. while (last && last->next)
  1947. {
  1948. last = last->next;
  1949. }
  1950. if (last)
  1951. {
  1952. processor->prev = last;
  1953. last->next = processor;
  1954. }
  1955. else stream.buffer->processor = processor;
  1956. ma_mutex_unlock(&AUDIO.System.lock);
  1957. }
  1958. // Remove processor from audio stream
  1959. void DetachAudioStreamProcessor(AudioStream stream, AudioCallback process)
  1960. {
  1961. ma_mutex_lock(&AUDIO.System.lock);
  1962. rAudioProcessor *processor = stream.buffer->processor;
  1963. while (processor)
  1964. {
  1965. rAudioProcessor *next = processor->next;
  1966. rAudioProcessor *prev = processor->prev;
  1967. if (processor->process == process)
  1968. {
  1969. if (stream.buffer->processor == processor) stream.buffer->processor = next;
  1970. if (prev) prev->next = next;
  1971. if (next) next->prev = prev;
  1972. RL_FREE(processor);
  1973. }
  1974. processor = next;
  1975. }
  1976. ma_mutex_unlock(&AUDIO.System.lock);
  1977. }
  1978. // Add processor to audio pipeline. Order of processors is important
  1979. // Works the same way as {Attach,Detach}AudioStreamProcessor() functions, except
  1980. // these two work on the already mixed output just before sending it to the sound hardware
  1981. void AttachAudioMixedProcessor(AudioCallback process)
  1982. {
  1983. ma_mutex_lock(&AUDIO.System.lock);
  1984. rAudioProcessor *processor = (rAudioProcessor *)RL_CALLOC(1, sizeof(rAudioProcessor));
  1985. processor->process = process;
  1986. rAudioProcessor *last = AUDIO.mixedProcessor;
  1987. while (last && last->next)
  1988. {
  1989. last = last->next;
  1990. }
  1991. if (last)
  1992. {
  1993. processor->prev = last;
  1994. last->next = processor;
  1995. }
  1996. else AUDIO.mixedProcessor = processor;
  1997. ma_mutex_unlock(&AUDIO.System.lock);
  1998. }
  1999. // Remove processor from audio pipeline
  2000. void DetachAudioMixedProcessor(AudioCallback process)
  2001. {
  2002. ma_mutex_lock(&AUDIO.System.lock);
  2003. rAudioProcessor *processor = AUDIO.mixedProcessor;
  2004. while (processor)
  2005. {
  2006. rAudioProcessor *next = processor->next;
  2007. rAudioProcessor *prev = processor->prev;
  2008. if (processor->process == process)
  2009. {
  2010. if (AUDIO.mixedProcessor == processor) AUDIO.mixedProcessor = next;
  2011. if (prev) prev->next = next;
  2012. if (next) next->prev = prev;
  2013. RL_FREE(processor);
  2014. }
  2015. processor = next;
  2016. }
  2017. ma_mutex_unlock(&AUDIO.System.lock);
  2018. }
  2019. //----------------------------------------------------------------------------------
  2020. // Module Internal Functions Definition
  2021. //----------------------------------------------------------------------------------
  2022. // Log callback function
  2023. static void OnLog(void *pUserData, ma_uint32 level, const char *pMessage)
  2024. {
  2025. TRACELOG(LOG_WARNING, "miniaudio: %s", pMessage); // All log messages from miniaudio are errors
  2026. }
  2027. // Reads audio data from an AudioBuffer object in internal format
  2028. static ma_uint32 ReadAudioBufferFramesInInternalFormat(AudioBuffer *audioBuffer, void *framesOut, ma_uint32 frameCount)
  2029. {
  2030. // Using audio buffer callback
  2031. if (audioBuffer->callback)
  2032. {
  2033. audioBuffer->callback(framesOut, frameCount);
  2034. audioBuffer->framesProcessed += frameCount;
  2035. return frameCount;
  2036. }
  2037. ma_uint32 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames;
  2038. ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
  2039. if (currentSubBufferIndex > 1) return 0;
  2040. // Another thread can update the processed state of buffers, so
  2041. // we just take a copy here to try and avoid potential synchronization problems
  2042. bool isSubBufferProcessed[2] = { 0 };
  2043. isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
  2044. isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1];
  2045. ma_uint32 frameSizeInBytes = ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
  2046. // Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0
  2047. ma_uint32 framesRead = 0;
  2048. while (1)
  2049. {
  2050. // We break from this loop differently depending on the buffer's usage
  2051. // - For static buffers, we simply fill as much data as we can
  2052. // - For streaming buffers we only fill half of the buffer that are processed
  2053. // Unprocessed halves must keep their audio data in-tact
  2054. if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC)
  2055. {
  2056. if (framesRead >= frameCount) break;
  2057. }
  2058. else
  2059. {
  2060. if (isSubBufferProcessed[currentSubBufferIndex]) break;
  2061. }
  2062. ma_uint32 totalFramesRemaining = (frameCount - framesRead);
  2063. if (totalFramesRemaining == 0) break;
  2064. ma_uint32 framesRemainingInOutputBuffer;
  2065. if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC)
  2066. {
  2067. framesRemainingInOutputBuffer = audioBuffer->sizeInFrames - audioBuffer->frameCursorPos;
  2068. }
  2069. else
  2070. {
  2071. ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames*currentSubBufferIndex;
  2072. framesRemainingInOutputBuffer = subBufferSizeInFrames - (audioBuffer->frameCursorPos - firstFrameIndexOfThisSubBuffer);
  2073. }
  2074. ma_uint32 framesToRead = totalFramesRemaining;
  2075. if (framesToRead > framesRemainingInOutputBuffer) framesToRead = framesRemainingInOutputBuffer;
  2076. memcpy((unsigned char *)framesOut + (framesRead*frameSizeInBytes), audioBuffer->data + (audioBuffer->frameCursorPos*frameSizeInBytes), framesToRead*frameSizeInBytes);
  2077. audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->sizeInFrames;
  2078. framesRead += framesToRead;
  2079. // If we've read to the end of the buffer, mark it as processed
  2080. if (framesToRead == framesRemainingInOutputBuffer)
  2081. {
  2082. audioBuffer->isSubBufferProcessed[currentSubBufferIndex] = true;
  2083. isSubBufferProcessed[currentSubBufferIndex] = true;
  2084. currentSubBufferIndex = (currentSubBufferIndex + 1)%2;
  2085. // We need to break from this loop if we're not looping
  2086. if (!audioBuffer->looping)
  2087. {
  2088. StopAudioBufferInLockedState(audioBuffer);
  2089. break;
  2090. }
  2091. }
  2092. }
  2093. // Zero-fill excess
  2094. ma_uint32 totalFramesRemaining = (frameCount - framesRead);
  2095. if (totalFramesRemaining > 0)
  2096. {
  2097. memset((unsigned char *)framesOut + (framesRead*frameSizeInBytes), 0, totalFramesRemaining*frameSizeInBytes);
  2098. // For static buffers we can fill the remaining frames with silence for safety, but we don't want
  2099. // to report those frames as "read". The reason for this is that the caller uses the return value
  2100. // to know whether a non-looping sound has finished playback
  2101. if (audioBuffer->usage != AUDIO_BUFFER_USAGE_STATIC) framesRead += totalFramesRemaining;
  2102. }
  2103. return framesRead;
  2104. }
  2105. // Reads audio data from an AudioBuffer object in device format, returned data will be in a format appropriate for mixing
  2106. static ma_uint32 ReadAudioBufferFramesInMixingFormat(AudioBuffer *audioBuffer, float *framesOut, ma_uint32 frameCount)
  2107. {
  2108. // What's going on here is that we're continuously converting data from the AudioBuffer's internal format to the mixing format, which
  2109. // should be defined by the output format of the data converter. We do this until frameCount frames have been output. The important
  2110. // detail to remember here is that we never, ever attempt to read more input data than is required for the specified number of output
  2111. // frames. This can be achieved with ma_data_converter_get_required_input_frame_count()
  2112. ma_uint8 inputBuffer[4096] = { 0 };
  2113. ma_uint32 inputBufferFrameCap = sizeof(inputBuffer)/ma_get_bytes_per_frame(audioBuffer->converter.formatIn, audioBuffer->converter.channelsIn);
  2114. ma_uint32 totalOutputFramesProcessed = 0;
  2115. while (totalOutputFramesProcessed < frameCount)
  2116. {
  2117. ma_uint64 outputFramesToProcessThisIteration = frameCount - totalOutputFramesProcessed;
  2118. ma_uint64 inputFramesToProcessThisIteration = 0;
  2119. (void)ma_data_converter_get_required_input_frame_count(&audioBuffer->converter, outputFramesToProcessThisIteration, &inputFramesToProcessThisIteration);
  2120. if (inputFramesToProcessThisIteration > inputBufferFrameCap)
  2121. {
  2122. inputFramesToProcessThisIteration = inputBufferFrameCap;
  2123. }
  2124. float *runningFramesOut = framesOut + (totalOutputFramesProcessed*audioBuffer->converter.channelsOut);
  2125. // At this point we can convert the data to our mixing format
  2126. ma_uint64 inputFramesProcessedThisIteration = ReadAudioBufferFramesInInternalFormat(audioBuffer, inputBuffer, (ma_uint32)inputFramesToProcessThisIteration);
  2127. ma_uint64 outputFramesProcessedThisIteration = outputFramesToProcessThisIteration;
  2128. ma_data_converter_process_pcm_frames(&audioBuffer->converter, inputBuffer, &inputFramesProcessedThisIteration, runningFramesOut, &outputFramesProcessedThisIteration);
  2129. totalOutputFramesProcessed += (ma_uint32)outputFramesProcessedThisIteration; // Safe cast
  2130. if (inputFramesProcessedThisIteration < inputFramesToProcessThisIteration) break; // Ran out of input data
  2131. // This should never be hit, but added here for safety
  2132. // Ensures we get out of the loop when no input nor output frames are processed
  2133. if ((inputFramesProcessedThisIteration == 0) && (outputFramesProcessedThisIteration == 0)) break;
  2134. }
  2135. return totalOutputFramesProcessed;
  2136. }
  2137. // Sending audio data to device callback function
  2138. // This function will be called when miniaudio needs more data
  2139. // NOTE: All the mixing takes place here
  2140. static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount)
  2141. {
  2142. (void)pDevice;
  2143. // Mixing is basically just an accumulation, we need to initialize the output buffer to 0
  2144. memset(pFramesOut, 0, frameCount*pDevice->playback.channels*ma_get_bytes_per_sample(pDevice->playback.format));
  2145. // Using a mutex here for thread-safety which makes things not real-time
  2146. // This is unlikely to be necessary for this project, but may want to consider how you might want to avoid this
  2147. ma_mutex_lock(&AUDIO.System.lock);
  2148. {
  2149. for (AudioBuffer *audioBuffer = AUDIO.Buffer.first; audioBuffer != NULL; audioBuffer = audioBuffer->next)
  2150. {
  2151. // Ignore stopped or paused sounds
  2152. if (!audioBuffer->playing || audioBuffer->paused) continue;
  2153. ma_uint32 framesRead = 0;
  2154. while (1)
  2155. {
  2156. if (framesRead >= frameCount) break;
  2157. // Just read as much data as we can from the stream
  2158. ma_uint32 framesToRead = (frameCount - framesRead);
  2159. while (framesToRead > 0)
  2160. {
  2161. float tempBuffer[1024] = { 0 }; // Frames for stereo
  2162. ma_uint32 framesToReadRightNow = framesToRead;
  2163. if (framesToReadRightNow > sizeof(tempBuffer)/sizeof(tempBuffer[0])/AUDIO_DEVICE_CHANNELS)
  2164. {
  2165. framesToReadRightNow = sizeof(tempBuffer)/sizeof(tempBuffer[0])/AUDIO_DEVICE_CHANNELS;
  2166. }
  2167. ma_uint32 framesJustRead = ReadAudioBufferFramesInMixingFormat(audioBuffer, tempBuffer, framesToReadRightNow);
  2168. if (framesJustRead > 0)
  2169. {
  2170. float *framesOut = (float *)pFramesOut + (framesRead*AUDIO.System.device.playback.channels);
  2171. float *framesIn = tempBuffer;
  2172. // Apply processors chain if defined
  2173. rAudioProcessor *processor = audioBuffer->processor;
  2174. while (processor)
  2175. {
  2176. processor->process(framesIn, framesJustRead);
  2177. processor = processor->next;
  2178. }
  2179. MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer);
  2180. framesToRead -= framesJustRead;
  2181. framesRead += framesJustRead;
  2182. }
  2183. if (!audioBuffer->playing)
  2184. {
  2185. framesRead = frameCount;
  2186. break;
  2187. }
  2188. // If we weren't able to read all the frames we requested, break
  2189. if (framesJustRead < framesToReadRightNow)
  2190. {
  2191. if (!audioBuffer->looping)
  2192. {
  2193. StopAudioBufferInLockedState(audioBuffer);
  2194. break;
  2195. }
  2196. else
  2197. {
  2198. // Should never get here, but just for safety,
  2199. // move the cursor position back to the start and continue the loop
  2200. audioBuffer->frameCursorPos = 0;
  2201. continue;
  2202. }
  2203. }
  2204. }
  2205. // If for some reason we weren't able to read every frame we'll need to break from the loop
  2206. // Not doing this could theoretically put us into an infinite loop
  2207. if (framesToRead > 0) break;
  2208. }
  2209. }
  2210. }
  2211. rAudioProcessor *processor = AUDIO.mixedProcessor;
  2212. while (processor)
  2213. {
  2214. processor->process(pFramesOut, frameCount);
  2215. processor = processor->next;
  2216. }
  2217. ma_mutex_unlock(&AUDIO.System.lock);
  2218. }
  2219. // Main mixing function, pretty simple in this project, just an accumulation
  2220. // NOTE: framesOut is both an input and an output, it is initially filled with zeros outside of this function
  2221. static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, AudioBuffer *buffer)
  2222. {
  2223. const float localVolume = buffer->volume;
  2224. const ma_uint32 channels = AUDIO.System.device.playback.channels;
  2225. if (channels == 2) // We consider panning
  2226. {
  2227. const float left = buffer->pan;
  2228. const float right = 1.0f - left;
  2229. // Fast sine approximation in [0..1] for pan law: y = 0.5f*x*(3 - x*x);
  2230. const float levels[2] = { localVolume*0.5f*left*(3.0f - left*left), localVolume*0.5f*right*(3.0f - right*right) };
  2231. float *frameOut = framesOut;
  2232. const float *frameIn = framesIn;
  2233. for (ma_uint32 frame = 0; frame < frameCount; frame++)
  2234. {
  2235. frameOut[0] += (frameIn[0]*levels[0]);
  2236. frameOut[1] += (frameIn[1]*levels[1]);
  2237. frameOut += 2;
  2238. frameIn += 2;
  2239. }
  2240. }
  2241. else // We do not consider panning
  2242. {
  2243. for (ma_uint32 frame = 0; frame < frameCount; frame++)
  2244. {
  2245. for (ma_uint32 c = 0; c < channels; c++)
  2246. {
  2247. float *frameOut = framesOut + (frame*channels);
  2248. const float *frameIn = framesIn + (frame*channels);
  2249. // Output accumulates input multiplied by volume to provided output (usually 0)
  2250. frameOut[c] += (frameIn[c]*localVolume);
  2251. }
  2252. }
  2253. }
  2254. }
  2255. // Check if an audio buffer is playing, assuming the audio system mutex has been locked
  2256. static bool IsAudioBufferPlayingInLockedState(AudioBuffer *buffer)
  2257. {
  2258. bool result = false;
  2259. if (buffer != NULL) result = (buffer->playing && !buffer->paused);
  2260. return result;
  2261. }
  2262. // Stop an audio buffer, assuming the audio system mutex has been locked
  2263. static void StopAudioBufferInLockedState(AudioBuffer *buffer)
  2264. {
  2265. if (buffer != NULL)
  2266. {
  2267. if (IsAudioBufferPlayingInLockedState(buffer))
  2268. {
  2269. buffer->playing = false;
  2270. buffer->paused = false;
  2271. buffer->frameCursorPos = 0;
  2272. buffer->framesProcessed = 0;
  2273. buffer->isSubBufferProcessed[0] = true;
  2274. buffer->isSubBufferProcessed[1] = true;
  2275. }
  2276. }
  2277. }
  2278. // Update audio stream, assuming the audio system mutex has been locked
  2279. static void UpdateAudioStreamInLockedState(AudioStream stream, const void *data, int frameCount)
  2280. {
  2281. if (stream.buffer != NULL)
  2282. {
  2283. if (stream.buffer->isSubBufferProcessed[0] || stream.buffer->isSubBufferProcessed[1])
  2284. {
  2285. ma_uint32 subBufferToUpdate = 0;
  2286. if (stream.buffer->isSubBufferProcessed[0] && stream.buffer->isSubBufferProcessed[1])
  2287. {
  2288. // Both buffers are available for updating
  2289. // Update the first one and make sure the cursor is moved back to the front
  2290. subBufferToUpdate = 0;
  2291. stream.buffer->frameCursorPos = 0;
  2292. }
  2293. else
  2294. {
  2295. // Just update whichever sub-buffer is processed
  2296. subBufferToUpdate = (stream.buffer->isSubBufferProcessed[0])? 0 : 1;
  2297. }
  2298. ma_uint32 subBufferSizeInFrames = stream.buffer->sizeInFrames/2;
  2299. unsigned char *subBuffer = stream.buffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);
  2300. stream.buffer->framesProcessed += frameCount;
  2301. // Does this API expect a whole buffer to be updated in one go?
  2302. // Assuming so, but if not will need to change this logic
  2303. if (subBufferSizeInFrames >= (ma_uint32)frameCount)
  2304. {
  2305. ma_uint32 framesToWrite = (ma_uint32)frameCount;
  2306. ma_uint32 bytesToWrite = framesToWrite*stream.channels*(stream.sampleSize/8);
  2307. memcpy(subBuffer, data, bytesToWrite);
  2308. // Any leftover frames should be filled with zeros
  2309. ma_uint32 leftoverFrameCount = subBufferSizeInFrames - framesToWrite;
  2310. if (leftoverFrameCount > 0) memset(subBuffer + bytesToWrite, 0, leftoverFrameCount*stream.channels*(stream.sampleSize/8));
  2311. stream.buffer->isSubBufferProcessed[subBufferToUpdate] = false;
  2312. }
  2313. else TRACELOG(LOG_WARNING, "STREAM: Attempting to write too many frames to buffer");
  2314. }
  2315. else TRACELOG(LOG_WARNING, "STREAM: Buffer not available for updating");
  2316. }
  2317. }
  2318. // Some required functions for audio standalone module version
  2319. #if defined(RAUDIO_STANDALONE)
  2320. // Check file extension
  2321. static bool IsFileExtension(const char *fileName, const char *ext)
  2322. {
  2323. bool result = false;
  2324. const char *fileExt;
  2325. if ((fileExt = strrchr(fileName, '.')) != NULL)
  2326. {
  2327. if (strcmp(fileExt, ext) == 0) result = true;
  2328. }
  2329. return result;
  2330. }
  2331. // Get pointer to extension for a filename string (includes the dot: .png)
  2332. static const char *GetFileExtension(const char *fileName)
  2333. {
  2334. const char *dot = strrchr(fileName, '.');
  2335. if (!dot || dot == fileName) return NULL;
  2336. return dot;
  2337. }
  2338. // String pointer reverse break: returns right-most occurrence of charset in s
  2339. static const char *strprbrk(const char *s, const char *charset)
  2340. {
  2341. const char *latestMatch = NULL;
  2342. for (; s = strpbrk(s, charset), s != NULL; latestMatch = s++) { }
  2343. return latestMatch;
  2344. }
  2345. // Get pointer to filename for a path string
  2346. static const char *GetFileName(const char *filePath)
  2347. {
  2348. const char *fileName = NULL;
  2349. if (filePath != NULL) fileName = strprbrk(filePath, "\\/");
  2350. if (!fileName) return filePath;
  2351. return fileName + 1;
  2352. }
  2353. // Get filename string without extension (uses static string)
  2354. static const char *GetFileNameWithoutExt(const char *filePath)
  2355. {
  2356. #define MAX_FILENAMEWITHOUTEXT_LENGTH 256
  2357. static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 };
  2358. memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH);
  2359. if (filePath != NULL) strcpy(fileName, GetFileName(filePath)); // Get filename with extension
  2360. int size = (int)strlen(fileName); // Get size in bytes
  2361. for (int i = 0; (i < size) && (i < MAX_FILENAMEWITHOUTEXT_LENGTH); i++)
  2362. {
  2363. if (fileName[i] == '.')
  2364. {
  2365. // NOTE: We break on first '.' found
  2366. fileName[i] = '\0';
  2367. break;
  2368. }
  2369. }
  2370. return fileName;
  2371. }
  2372. // Load data from file into a buffer
  2373. static unsigned char *LoadFileData(const char *fileName, int *dataSize)
  2374. {
  2375. unsigned char *data = NULL;
  2376. *dataSize = 0;
  2377. if (fileName != NULL)
  2378. {
  2379. FILE *file = fopen(fileName, "rb");
  2380. if (file != NULL)
  2381. {
  2382. // WARNING: On binary streams SEEK_END could not be found,
  2383. // using fseek() and ftell() could not work in some (rare) cases
  2384. fseek(file, 0, SEEK_END);
  2385. int size = ftell(file);
  2386. fseek(file, 0, SEEK_SET);
  2387. if (size > 0)
  2388. {
  2389. data = (unsigned char *)RL_MALLOC(size*sizeof(unsigned char));
  2390. // NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements]
  2391. unsigned int count = (unsigned int)fread(data, sizeof(unsigned char), size, file);
  2392. *dataSize = count;
  2393. if (count != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded", fileName);
  2394. else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
  2395. }
  2396. else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to read file", fileName);
  2397. fclose(file);
  2398. }
  2399. else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
  2400. }
  2401. else TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
  2402. return data;
  2403. }
  2404. // Save data to file from buffer
  2405. static bool SaveFileData(const char *fileName, void *data, int dataSize)
  2406. {
  2407. if (fileName != NULL)
  2408. {
  2409. FILE *file = fopen(fileName, "wb");
  2410. if (file != NULL)
  2411. {
  2412. unsigned int count = (unsigned int)fwrite(data, sizeof(unsigned char), dataSize, file);
  2413. if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write file", fileName);
  2414. else if (count != dataSize) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially written", fileName);
  2415. else TRACELOG(LOG_INFO, "FILEIO: [%s] File saved successfully", fileName);
  2416. fclose(file);
  2417. }
  2418. else
  2419. {
  2420. TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open file", fileName);
  2421. return false;
  2422. }
  2423. }
  2424. else
  2425. {
  2426. TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
  2427. return false;
  2428. }
  2429. return true;
  2430. }
  2431. // Save text data to file (write), string must be '\0' terminated
  2432. static bool SaveFileText(const char *fileName, char *text)
  2433. {
  2434. if (fileName != NULL)
  2435. {
  2436. FILE *file = fopen(fileName, "wt");
  2437. if (file != NULL)
  2438. {
  2439. int count = fprintf(file, "%s", text);
  2440. if (count == 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to write text file", fileName);
  2441. else TRACELOG(LOG_INFO, "FILEIO: [%s] Text file saved successfully", fileName);
  2442. fclose(file);
  2443. }
  2444. else
  2445. {
  2446. TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to open text file", fileName);
  2447. return false;
  2448. }
  2449. }
  2450. else
  2451. {
  2452. TRACELOG(LOG_WARNING, "FILEIO: File name provided is not valid");
  2453. return false;
  2454. }
  2455. return true;
  2456. }
  2457. #endif
  2458. #undef AudioBuffer
  2459. #endif // SUPPORT_MODULE_RAUDIO