MEMSOUND: Difference between revisions
Jump to navigation
Jump to search
Navigation:
Main Page with Articles and Tutorials
Keyword Reference - Alphabetical
Keyword Reference - By usage
Report a broken link
(Changes due to removal of OpenAL) |
(Fix example 2 not working on Windows 32-bit) |
||
Line 115: | Line 115: | ||
;Example 2:Plotting a sound's waves. | ;Example 2:Plotting a sound's waves. | ||
{{CodeStart}} | {{CodeStart}} | ||
{{Cl| | {{Cl|OPTION}} {{Cl|_EXPLICIT}} | ||
{{Cl| | |||
{{Cl| | {{Cl|DECLARE LIBRARY}} | ||
{{Cm|$IF}} {{Text|32BIT|#F580B1}} {{Cm|THEN}} | |||
{{Cl|FUNCTION}} {{Text|ConvertOffset~&|#55FF55}} {{Cl|ALIAS}} {{Text|<nowiki>"uintptr_t"</nowiki>|#FFB100}} ({{Cl|BYVAL}} o {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_OFFSET (function)|_OFFSET}}) | |||
{{Cm|$ELSE}} | |||
{{Cl|FUNCTION}} {{Text|ConvertOffset~&&|#55FF55}} {{Cl|ALIAS}} {{Text|<nowiki>"uintptr_t"</nowiki>|#FFB100}} ({{Cl|BYVAL}} o {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_OFFSET (function)|_OFFSET}}) | |||
{{Cm|$END IF}} | |||
{{Cl|END DECLARE}} | |||
{{Cl|PRINT}} "Loading..."; | {{Cl|SCREEN}} {{Cl|_NEWIMAGE}}({{Text|800|#F580B1}}, {{Text|327|#F580B1}}, {{Text|32|#F580B1}}) | ||
{{Cl|DIM}} Song {{Cl|AS}} {{Cl|LONG}} | |||
Song = {{Cl|_SNDOPEN}}("OPL3 Groove.rad") ' | {{Cl|PRINT}} {{Text|<nowiki>"Loading..."</nowiki>|#FFB100}}; | ||
{{Cl|IF}} Song < 1 {{Cl|THEN}} | {{Cl|DIM}} Song {{Cl|AS}} {{Cl|LONG}}: Song = {{Cl|_SNDOPEN}}({{Text|<nowiki>"OPL3 Groove.rad"</nowiki>|#FFB100}}) {{Text|<nowiki>' replace this with your ( WAV, AIFF, AIFC, FLAC, OGG, MP3, MID, IT, XM, S3M, MOD, RAD, AHX, HVL) sound file</nowiki>|#919191}} | ||
{{Cl|PRINT}} "Failed to load song!" | {{Cl|IF}} Song < {{Text|1|#F580B1}} {{Cl|THEN}} | ||
{{Cl|PRINT}} {{Text|<nowiki>"Failed to load song!"</nowiki>|#FFB100}} | |||
{{Cl|END}} | {{Cl|END}} | ||
{{Cl|END}} {{Cl| | {{Cl|END IF}} | ||
{{ | {{Cl|PRINT}} {{Text|<nowiki>"Done!"</nowiki>|#FFB100}} | ||
{{Cl|_SNDPLAY}} Song | {{Cl|_SNDPLAY}} Song | ||
{{Cl|DIM}} SampleData {{Cl|AS}} {{Cl|_MEM}} | {{Cl|DIM}} SampleData {{Cl|AS}} {{Cl|_MEM}}: SampleData = {{Cl|_MEMSOUND}}(Song, {{Text|0|#F580B1}}) | ||
SampleData = {{Cl|_MEMSOUND}}(Song, 0) | {{Cl|IF}} SampleData.SIZE = {{Text|0|#F580B1}} {{Cl|THEN}} | ||
{{Cl|IF}} SampleData.SIZE = 0 {{Cl|THEN}} | {{Cl|PRINT}} {{Text|<nowiki>"Failed to access sound sample data."</nowiki>|#FFB100}} | ||
{{Cl|PRINT}} "Failed to access sound sample data." | |||
{{Cl|END}} | {{Cl|END}} | ||
{{Cl|END | {{Cl|END IF}} | ||
{{Cl|DIM}} sz {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_INTEGER64}}: sz = {{Text|ConvertOffset|#55FF55}}(SampleData.ELEMENTSIZE) {{Text|<nowiki>' sz is the total size of the sound in bytes</nowiki>|#919191}} | |||
{{Cl|DIM}} x {{Cl|AS}} {{Cl|LONG}}, i {{Cl|AS}} {{Cl|_UNSIGNED}} {{Cl|_INTEGER64}} | |||
{{Cl|DO}} {{Cl| | {{Cl|DO...LOOP|DO UNTIL}} {{Cl|_KEYHIT}} = {{Text|27|#F580B1}} {{Cl|OR (boolean)|OR}} {{Cl|NOT}} {{Cl|_SNDPLAYING}}(Song) {{Cl|OR (boolean)|OR}} i + ({{Cl|_WIDTH (function)|_WIDTH}} * sz) > SampleData.SIZE | ||
{{Cl|CLS}} | {{Cl|CLS}} | ||
{{Cl|LOCATE}} 1, 1: {{Cl|PRINT}} i; "/"; SampleData.SIZE, "Frame Size ="; sz, "Data Type ="; SampleData.TYPE | {{Cl|LOCATE}} {{Text|1|#F580B1}}, {{Text|1|#F580B1}}: {{Cl|PRINT}} i; {{Text|<nowiki>"/"</nowiki>|#FFB100}}; SampleData.SIZE, {{Text|<nowiki>"Frame Size ="</nowiki>|#FFB100}}; sz, {{Text|<nowiki>"Data Type ="</nowiki>|#FFB100}}; SampleData.TYPE | ||
{{ | {{Cm|$CHECKING}}:{{Cl|OFF}} | ||
{{Cl|IF}} SampleData.TYPE = 130 {{Cl|THEN}} ' integer stereo or mono | {{Cl|IF}} SampleData.TYPE = {{Text|130|#F580B1}} {{Cl|THEN}} {{Text|<nowiki>' 128 OR 2: integer stereo or mono</nowiki>|#919191}} | ||
{{Cl|FOR}} x = 0 {{Cl|TO}} {{Cl|_WIDTH}} - 1 | {{Cl|FOR}} x = {{Text|0|#F580B1}} {{Cl|TO}} {{Cl|_WIDTH (function)|_WIDTH}} - {{Text|1|#F580B1}} | ||
si = {{Cl|_MEMGET}}(SampleData, SampleData.OFFSET + i + x * sz, {{Cl|INTEGER}}) 'get sound data | {{Cl|DIM}} si {{Cl|AS}} {{Cl|INTEGER}}: si = {{Cl|_MEMGET (function)|_MEMGET}}(SampleData, SampleData.OFFSET + i + x * sz, {{Cl|INTEGER}}) {{Text|<nowiki>' get sound data</nowiki>|#919191}} | ||
{{Cl|LINE}} (x, {{Cl|_HEIGHT}} / 2)-{{Cl|STEP}}(0, 300 * si / 32768), {{Cl|_RGB32}}(0, 111, 0) 'plot wave | {{Cl|LINE}} (x, {{Cl|_HEIGHT}} / {{Text|2|#F580B1}})-{{Cl|STEP}}({{Text|0|#F580B1}}, {{Text|300|#F580B1}} * si / {{Text|32768|#F580B1}}), {{Cl|_RGB32}}({{Text|0|#F580B1}}, {{Text|111|#F580B1}}, {{Text|0|#F580B1}}) {{Text|<nowiki>'plot wave</nowiki>|#919191}} | ||
{{Cl|NEXT}} | {{Cl|NEXT}} | ||
{{Cl|ELSEIF}} SampleData.TYPE = 260 {{Cl|THEN}} ' floating point stereo or mono | {{Cl|ELSEIF}} SampleData.TYPE = {{Text|260|#F580B1}} {{Cl|THEN}} {{Text|<nowiki>' 256 OR 4: floating point stereo or mono</nowiki>|#919191}} | ||
{{Cl|FOR}} x = 0 {{Cl|TO}} {{Cl|_WIDTH}} - 1 | {{Cl|FOR}} x = {{Text|0|#F580B1}} {{Cl|TO}} {{Cl|_WIDTH (function)|_WIDTH}} - {{Text|1|#F580B1}} | ||
sf = {{Cl|_MEMGET}}(SampleData, SampleData.OFFSET + i + x * sz, {{Cl|SINGLE}}) 'get sound data | {{Cl|DIM}} sf {{Cl|AS}} {{Cl|SINGLE}}: sf = {{Cl|_MEMGET (function)|_MEMGET}}(SampleData, SampleData.OFFSET + i + x * sz, {{Cl|SINGLE}}) {{Text|<nowiki>' get sound data</nowiki>|#919191}} | ||
{{Cl|LINE}} (x, {{Cl|_HEIGHT}} / 2)-{{Cl|STEP}}(0, sf * 300), {{Cl|_RGB32}}(0, 111, 0) 'plot wave | {{Cl|LINE}} (x, {{Cl|_HEIGHT}} / {{Text|2|#F580B1}})-{{Cl|STEP}}({{Text|0|#F580B1}}, sf * {{Text|300|#F580B1}}), {{Cl|_RGB32}}({{Text|0|#F580B1}}, {{Text|111|#F580B1}}, {{Text|0|#F580B1}}) {{Text|<nowiki>'plot wave</nowiki>|#919191}} | ||
{{Cl|NEXT}} | {{Cl|NEXT}} | ||
{{Cl|ELSEIF}} | {{Cl|ELSEIF}} SampleData.TYPE = {{Text|1153|#F580B1}} {{Cl|THEN}} {{Text|<nowiki>' 128 OR 1 OR 1024: unsigned byte stereo or mono</nowiki>|#919191}} | ||
{{Cl|FOR}} x = 0 {{Cl|TO}} {{Cl|_WIDTH}} - 1 | {{Cl|FOR}} x = {{Text|0|#F580B1}} {{Cl|TO}} {{Cl|_WIDTH (function)|_WIDTH}} - {{Text|1|#F580B1}} | ||
{{Cl|DIM}} sb {{Cl|AS}} {{Cl|_BYTE}}: sb = {{Cl|_MEMGET (function)|_MEMGET}}(SampleData, SampleData.OFFSET + i + x * sz, {{Cl|_UNSIGNED}} {{Cl|_BYTE}}) {{Cl|XOR}} {{Text|&H80|#F580B1}} {{Text|<nowiki>' get sound data and convert to signed</nowiki>|#919191}} | |||
{{Cl|LINE}} (x, {{Cl|_HEIGHT}} / 2)-{{Cl|STEP}}(0, 300 * | {{Cl|LINE}} (x, {{Cl|_HEIGHT}} / {{Text|2|#F580B1}})-{{Cl|STEP}}({{Text|0|#F580B1}}, {{Text|300|#F580B1}} * sb / {{Text|128|#F580B1}}), {{Cl|_RGB32}}({{Text|0|#F580B1}}, {{Text|111|#F580B1}}, {{Text|0|#F580B1}}) {{Text|<nowiki>' plot wave</nowiki>|#919191}} | ||
{{Cl|NEXT}} | {{Cl|NEXT}} | ||
{{Cl|END | {{Cl|END IF}} | ||
{{ | {{Cm|$CHECKING}}:{{Cl|ON}} | ||
{{Cl|_DISPLAY}} | {{Cl|_DISPLAY}} | ||
{{Cl|_LIMIT}} 60 | {{Cl|_LIMIT}} {{Text|60|#F580B1}} | ||
i = {{Cl|FIX}}({{Cl|_SNDGETPOS}}(Song) * {{Cl|_SNDRATE}}) * sz ' | i = {{Cl|FIX}}({{Cl|_SNDGETPOS}}(Song) * {{Cl|_SNDRATE}}) * sz {{Text|<nowiki>' calculate the new sample frame position</nowiki>|#919191}} | ||
{{Cl|LOOP}} | {{Cl|LOOP}} | ||
{{Cl|_SNDCLOSE}} Song 'closing the sound releases the mem blocks | {{Cl|_SNDCLOSE}} Song {{Text|<nowiki>' closing the sound releases the mem blocks</nowiki>|#919191}} | ||
{{Cl|_AUTODISPLAY}} | {{Cl|_AUTODISPLAY}} | ||
{{Cl|END}} | {{Cl|END}} |
Revision as of 23:09, 24 September 2023
The _MEMSOUND function returns a _MEM value referring to a sound's raw data in memory using a designated sound handle created by the _SNDOPEN or _SNDNEW function.
Syntax
- soundBlock = _MEMSOUND(soundHandle&[, channel&])
Parameters
- The soundBlock _MEM type variable holds the read-only elements .OFFSET, .SIZE, .ELEMENTSIZE, .TYPE and .SOUND.
- .OFFSET is the starting memory address of the sound sample data.
- .SIZE is the size of the sample data in bytes
- .ELEMENTSIZE will contain the number of bytes-per-sample the audio contains.
- Can return 1 (8-bit mono), 2 (8-bit stereo), 2 (16-bit mono), 4 (16-bit stereo), 4 (32-bit mono) or 8 (32-bit stereo).
- Use .TYPE to determine the data type of the sample data.
- .TYPE will contain the data type of the sample data. See _MEM for details.
- .SOUND will contain the same handle value as returned by the _SNDOPEN function.
- The second parameter channel& is optional and deprecated. This was used to specify the sound channel. In QB64-PE v3.1.0 and above stereo data is always interleaved. You must use .ELEMENTSIZE and .TYPE to determine the type of audio data you are dealing with.
Description
- Use this function to obtain a pointer to the raw sound data in memory for direct access.
- Even if the memory pointer obtained by this fuction was already freed again using _MEMFREE, the respective Sound handle itself must still be freed using _SNDCLOSE when no longer required.
- If .SIZE returns 0, that means the data could not be accessed. It may happen if you try to access the right channel in a mono file or the format simply does not support accessing raw PCM samples.
- channel& - 1 (left channel/mono) or 2 (right channel; for stereo files) was supported on the old OpenAL backend. For the new miniaudio backend, this must be 0.
Availability
- QB64 v1.5 and up
- QB64-PE all versions
Examples
- Example 1
- Checking that a sound file is stereo.
OPTION _EXPLICIT PRINT "Loading..."; DIM Song AS LONG Song = _SNDOPEN("onward_ride1.flac") ' Replace file name with your sound file IF Song < 1 THEN PRINT "Failed to load sound!" END END IF PRINT "Done!" DIM Channels AS _UNSIGNED _BYTE Channels = SndChannels(Song) IF Channels = 2 THEN PRINT "This file is STEREO" ELSEIF Channels = 1 THEN PRINT "This file is MONO" ELSE PRINT "An error occurred." END IF _SNDCLOSE Song 'closing the sound releases the mem blocks END ' This function returns the number of sound channels for a valid sound "handle" ' 2 = stereo, 1 = mono, 0 = error FUNCTION SndChannels~%% (handle AS LONG) DIM SampleData AS _MEM SndChannels = 0 ' Assume failure ' Check if the sound is valid SampleData = _MEMSOUND(handle, 0) IF SampleData.SIZE = 0 THEN EXIT FUNCTION END IF ' Check the data type and then decide if the sound is stereo or mono IF SampleData.TYPE = 260 THEN ' 32-bit floating point IF SampleData.ELEMENTSIZE = 4 THEN SndChannels = 1 ELSEIF SampleData.ELEMENTSIZE = 8 THEN SndChannels = 2 END IF ELSEIF SampleData.TYPE = 132 THEN ' 32-bit integer IF SampleData.ELEMENTSIZE = 4 THEN SndChannels = 1 ELSEIF SampleData.ELEMENTSIZE = 8 THEN SndChannels = 2 END IF ELSEIF SampleData.TYPE = 130 THEN ' 16-bit integer IF SampleData.ELEMENTSIZE = 2 THEN SndChannels = 1 ELSEIF SampleData.ELEMENTSIZE = 4 THEN SndChannels = 2 END IF ELSEIF SampleData.TYPE = 1153 THEN ' 8-bit unsigned integer IF SampleData.ELEMENTSIZE = 1 THEN SndChannels = 1 ELSEIF SampleData.ELEMENTSIZE = 2 THEN SndChannels = 2 END IF ELSEIF SampleData.TYPE = 0 THEN ' This means this is an OpenAL sound handle DIM RightChannel AS _MEM RightChannel = _MEMSOUND(handle, 2) IF RightChannel.SIZE > 0 THEN SndChannels = 2 ELSE SndChannels = 1 END IF END IF END FUNCTION |
- Example 2
- Plotting a sound's waves.
OPTION _EXPLICIT DECLARE LIBRARY $IF 32BIT THEN FUNCTION ConvertOffset~& ALIAS "uintptr_t" (BYVAL o AS _UNSIGNED _OFFSET) $ELSE FUNCTION ConvertOffset~&& ALIAS "uintptr_t" (BYVAL o AS _UNSIGNED _OFFSET) $END IF END DECLARE SCREEN _NEWIMAGE(800, 327, 32) PRINT "Loading..."; DIM Song AS LONG: Song = _SNDOPEN("OPL3 Groove.rad") ' replace this with your ( WAV, AIFF, AIFC, FLAC, OGG, MP3, MID, IT, XM, S3M, MOD, RAD, AHX, HVL) sound file IF Song < 1 THEN PRINT "Failed to load song!" END END IF PRINT "Done!" _SNDPLAY Song DIM SampleData AS _MEM: SampleData = _MEMSOUND(Song, 0) IF SampleData.SIZE = 0 THEN PRINT "Failed to access sound sample data." END END IF DIM sz AS _UNSIGNED _INTEGER64: sz = ConvertOffset(SampleData.ELEMENTSIZE) ' sz is the total size of the sound in bytes DIM x AS LONG, i AS _UNSIGNED _INTEGER64 DO UNTIL _KEYHIT = 27 OR NOT _SNDPLAYING(Song) OR i + (_WIDTH * sz) > SampleData.SIZE CLS LOCATE 1, 1: PRINT i; "/"; SampleData.SIZE, "Frame Size ="; sz, "Data Type ="; SampleData.TYPE $CHECKING:OFF IF SampleData.TYPE = 130 THEN ' 128 OR 2: integer stereo or mono FOR x = 0 TO _WIDTH - 1 DIM si AS INTEGER: si = _MEMGET(SampleData, SampleData.OFFSET + i + x * sz, INTEGER) ' get sound data LINE (x, _HEIGHT / 2)-STEP(0, 300 * si / 32768), _RGB32(0, 111, 0) 'plot wave NEXT ELSEIF SampleData.TYPE = 260 THEN ' 256 OR 4: floating point stereo or mono FOR x = 0 TO _WIDTH - 1 DIM sf AS SINGLE: sf = _MEMGET(SampleData, SampleData.OFFSET + i + x * sz, SINGLE) ' get sound data LINE (x, _HEIGHT / 2)-STEP(0, sf * 300), _RGB32(0, 111, 0) 'plot wave NEXT ELSEIF SampleData.TYPE = 1153 THEN ' 128 OR 1 OR 1024: unsigned byte stereo or mono FOR x = 0 TO _WIDTH - 1 DIM sb AS _BYTE: sb = _MEMGET(SampleData, SampleData.OFFSET + i + x * sz, _UNSIGNED _BYTE) XOR &H80 ' get sound data and convert to signed LINE (x, _HEIGHT / 2)-STEP(0, 300 * sb / 128), _RGB32(0, 111, 0) ' plot wave NEXT END IF $CHECKING:ON _DISPLAY _LIMIT 60 i = FIX(_SNDGETPOS(Song) * _SNDRATE) * sz ' calculate the new sample frame position LOOP _SNDCLOSE Song ' closing the sound releases the mem blocks _AUTODISPLAY END |
See also