SNDRAW: Difference between revisions

From QB64 Phoenix Edition Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{DISPLAYTITLE:_SNDRAW}}
{{DISPLAYTITLE:_SNDRAW}}
The [[_SNDRAW]] statement plays sound wave sample frequencies created by a program.
The '''_SNDRAW''' statement plays sound wave sample frequencies created by a program.




Line 15: Line 15:
* Specifying {{Parameter|pipeHandle&}} allows sound to be played through two or more channels at the same time ('''version 1.000 and up''').
* Specifying {{Parameter|pipeHandle&}} allows sound to be played through two or more channels at the same time ('''version 1.000 and up''').
* If only {{Parameter|leftSample}} value is used, the sound will come out of both speakers.
* If only {{Parameter|leftSample}} value is used, the sound will come out of both speakers.
* Using _SNDRAW will pause any currently playing music.
* _SNDRAW is designed for continuous play. It will not produce any sound until a significant number of samples have been queued. No sound is played if only a few samples are queued.
* _SNDRAW is designed for continuous play. It will not produce any sound until a significant number of samples have been queued. No sound is played if only a few samples are queued.
* Ensure that [[_SNDRAWLEN]] is comfortably above 0 (until you've actually finished playing sound). If you are getting occasional unintended random clicks, this generally means that [[_SNDRAWLEN]] has dropped to 0.
* Ensure that [[_SNDRAWLEN]] is comfortably above 0 (until you've finished playing sound). If you get occasional unintended random clicks, this generally means that [[_SNDRAWLEN]] has dropped to 0.
* _SNDRAW is not intended to queue up many minutes worth of sound. It will probably work but will chew up a lot of memory (and if it gets swapped to disk, your sound could be interrupted abruptly).
* _SNDRAW is not intended to queue up many minutes worth of sound. It will probably work but will chew up a lot of memory (and if it gets swapped to disk, your sound could be interrupted abruptly).
* [[_SNDRATE]] determines how many samples are played per second, but timing is done by the sound card, not your program.
* [[_SNDRATE]] determines how many samples are played per second, but timing is done by the sound card, not your program.
* '''Do not attempt to use [[_TIMER]] or [[_DELAY]] or [[_LIMIT]] to control the timing of _SNDRAW. You may use them for delays or to limit your program's CPU usage, but how much to queue should only be based on the [[_SNDRAWLEN]].'''
* '''Do not attempt to use [[_TIMER]] or [[_DELAY]] or [[_LIMIT]] to control the timing of _SNDRAW. You may use them for delays or to limit your program's CPU usage, but how much to queue should only be based on the [[_SNDRAWLEN]].'''
{{PageAvailability}}
<!-- QB64 = a version or none, QBPE = a version or all, Platforms = yes or no -->
<gallery widths="48px" heights="48px" mode="nolines">
File:Qb64.png|'''v0.927'''
File:Qbpe.png|'''all'''
File:Apix.png
File:Win.png|'''yes'''
File:Lnx.png|'''yes'''
File:Osx.png|'''yes'''
</gallery>
<!-- Additional availability notes go below here -->




{{PageExamples}}
{{PageExamples}}
''Example 1:'' Sound using a sine wave with _SNDRAW Amplitude * SIN(8 * ATN(1) * Duration * (Frequency / _SNDRATE))
;Example 1:Sound using a sine wave with _SNDRAW Amplitude * SIN(8 * ATN(1) * Duration * (Frequency / _SNDRATE))
{{CodeStart}}
{{CodeStart}}
FREQ = 400                             'any frequency desired from 36 to 10,000
{{Text|FREQ|#55FF55}} = {{Text|400|#F580B1}} {{Text|<nowiki>'any frequency desired from 36 to 10,000</nowiki>|#919191}}
Pi2 = 8 * {{Cl|ATN}}(1)                       '2 * pi
Pi2 = {{Text|8|#F580B1}} * {{Cl|ATN}}({{Text|1|#F580B1}}) {{Text|<nowiki>'2 * pi</nowiki>|#919191}}
Amplitude = .3                         'amplitude of the signal from -1.0 to 1.0
Amplitude = {{Text|.3|#F580B1}} {{Text|<nowiki>'amplitude of the signal from -1.0 to 1.0</nowiki>|#919191}}
SampleRate = {{Cl|_SNDRATE}}                 'sets the sample rate
SampleRate = {{Cl|_SNDRATE}} {{Text|<nowiki>'sets the sample rate</nowiki>|#919191}}
FRate = FREQ / SampleRate'
FRate = {{Text|FREQ|#55FF55}} / SampleRate {{Text|<nowiki>'</nowiki>|#919191}}
{{Cl|FOR...NEXT|FOR}} Duration = 0 {{Cl|TO}} 5 * SampleRate     'play 5 seconds
{{Cl|FOR}} Duration = {{Text|0|#F580B1}} {{Cl|TO}} {{Text|5|#F580B1}} * SampleRate {{Text|<nowiki>'play 5 seconds</nowiki>|#919191}}
        {{Cl|_SNDRAW}} Amplitude * {{Cl|SIN}}(Pi2 * Duration * FRate)           'sine wave
    {{Cl|_SNDRAW}} Amplitude * {{Cl|SIN}}(Pi2 * Duration * FRate) {{Text|<nowiki>'sine wave</nowiki>|#919191}}
      '{{Cl|_SNDRAW}} Amplitude * {{Cl|SGN}}({{Cl|SIN}}(Pi2 * Duration * FRate))      'square wave
    {{Text|<nowiki>'_SNDRAW Amplitude * SGN(SIN(Pi2 * Duration * FRate))      'square wave</nowiki>|#919191}}
{{Cl|NEXT}}
{{Cl|NEXT}}
{{Cl|_SNDRAWDONE}}
{{Cl|_SNDRAWDONE}}
{{Cl|DO}}: LOOP {{Cl|WHILE}} {{Cl|_SNDRAWLEN}}
{{Cl|DO}}: {{Cl|DO...LOOP|LOOP WHILE}} {{Cl|_SNDRAWLEN}}
{{Cl|END}}
{{Cl|END}}
{{CodeEnd}}
{{CodeEnd}}
Line 43: Line 55:




''Example 2:'' A simple ringing bell tone that tapers off.
;Example 2:A simple ringing bell tone that tapers off.
{{CodeStart}}t = 0
{{CodeStart}}
tmp$ = "Sample = ##.#####  Time = ##.#####"
t = {{Text|0|#F580B1}}
LOCATE 1, 60: PRINT "Rate:"; {{Cl|_SNDRATE}}
tmp$ = {{Text|<nowiki>"Sample = ##.#####  Time = ##.#####"</nowiki>|#FFB100}}
DO
{{Cl|LOCATE}} {{Text|1|#F580B1}}, {{Text|60|#F580B1}}: {{Cl|PRINT}} {{Text|<nowiki>"Rate:"</nowiki>|#FFB100}}; {{Cl|_SNDRATE}}
  'queue some sound
{{Cl|DO}}
  DO WHILE {{Cl|_SNDRAWLEN}} < 0.2             'you may wish to adjust this
    {{Text|<nowiki>'queue some sound</nowiki>|#919191}}
    sample = {{Cl|SIN}}(t * 440 * {{Cl|ATN}}(1) * 8) '440Hz sine wave (t * 440 * )
    {{Cl|DO...LOOP|DO WHILE}} {{Cl|_SNDRAWLEN}} &lt; {{Text|0.2|#F580B1}} {{Text|<nowiki>'you may wish to adjust this</nowiki>|#919191}}
    sample = sample * {{Cl|EXP}}(-t * 3)       'fade out eliminates clicks after sound
        sample = {{Cl|SIN}}(t * {{Text|440|#F580B1}} * {{Cl|ATN}}({{Text|1|#F580B1}}) * {{Text|8|#F580B1}}) {{Text|<nowiki>'440Hz sine wave (t * 440 * 2p)</nowiki>|#919191}}
    {{Cl|_SNDRAW}} sample
        sample = sample * {{Cl|EXP}}(-t * {{Text|3|#F580B1}}) {{Text|<nowiki>'fade out eliminates clicks after sound</nowiki>|#919191}}
    t = t + 1 / {{Cl|_SNDRATE}}               'sound card sample frequency determines time
        {{Cl|_SNDRAW}} sample
  LOOP
        t = t + {{Text|1|#F580B1}} / {{Cl|_SNDRATE}} {{Text|<nowiki>'sound card sample frequency determines time</nowiki>|#919191}}
    {{Cl|LOOP}}


  'do other stuff, but it may interrupt sound
    {{Text|<nowiki>'do other stuff, but it may interrupt sound</nowiki>|#919191}}
  LOCATE 1, 1: PRINT USING tmp$; sample; t
    {{Cl|LOCATE}} {{Text|1|#F580B1}}, {{Text|1|#F580B1}}: {{Cl|PRINT USING}} tmp$; sample; t
LOOP WHILE t < 3.0                     'play for 3 seconds
{{Cl|DO...LOOP|LOOP WHILE}} t &lt; {{Text|3.0|#F580B1}} {{Text|<nowiki>'play for 3 seconds</nowiki>|#919191}}


{{Cl|_SNDRAWDONE}}
{{Cl|_SNDRAWDONE}}
DO WHILE {{Cl|_SNDRAWLEN}} > 0                'Finish any left over queued sound!
{{Cl|DO...LOOP|DO WHILE}} {{Cl|_SNDRAWLEN}} &gt; {{Text|0|#F580B1}} {{Text|<nowiki>'Finish any left over queued sound!</nowiki>|#919191}}
LOOP
{{Cl|LOOP}}
{{Cl|END}}
{{Cl|END}}
{{CodeEnd}}
{{CodeEnd}}
{{Small|Code by Artelius (responsible for the implementation of _SNDRAW)}}
{{Small|Code by Artelius}}




''Example 3:'' Routine uses _SNDRAW to display and play 12 notes from octaves 1 through 9.
;Example 3:Routine uses _SNDRAW to display and play 12 notes from octaves 1 through 9.
{{CodeStart}}
{{CodeStart}}
{{Cl|DIM}} {{Cl|SHARED}} rate&
{{Cl|DIM}} {{Cl|SHARED}} rate&
rate& = {{Cl|_SNDRATE}}
rate& = {{Cl|_SNDRATE}}
DO
{{Cl|DO}}
  {{Cl|PRINT}} "Enter the octave 1 to 8 (0 quits!):";
    {{Cl|PRINT}} {{Text|<nowiki>"Enter the octave 1 to 8 (0 quits!):"</nowiki>|#FFB100}};
  oct% = {{Cl|VAL}}({{Cl|INPUT$}}(1)): {{Cl|PRINT}} oct%
    oct% = {{Cl|VAL}}({{Cl|INPUT$}}({{Text|1|#F580B1}})): {{Cl|PRINT}} oct%
  {{Cl|IF...THEN|IF}} oct% = 0 {{Cl|THEN}} {{Cl|EXIT DO}}
    {{Cl|IF}} oct% = {{Text|0|#F580B1}} {{Cl|THEN}} {{Cl|EXIT DO}}
  octave = oct% - 4 '440 is in the 4th octave, 9th note
    octave = oct% - {{Text|4|#F580B1}} {{Text|<nowiki>'440 is in the 4th octave, 9th note</nowiki>|#919191}}
  {{Cl|COLOR}} oct% + 1
    {{Cl|COLOR}} oct% + {{Text|1|#F580B1}}
  {{Cl|PRINT USING}} "Octave: ##"; oct%
    {{Cl|PRINT USING}} {{Text|<nowiki>"Octave: ##"</nowiki>|#FFB100}}; oct%
  {{Cl|FOR...NEXT|FOR}} Note = 0 {{Cl|TO}} 11 'notes C to B
    {{Cl|FOR}} Note = {{Text|0|#F580B1}} {{Cl|TO}} {{Text|11|#F580B1}} {{Text|<nowiki>'notes C to B</nowiki>|#919191}}
    fq = FreQ(octave, Note, note$)
        fq = {{Text|FreQ|#55FF55}}(octave, Note, note$)
    {{Cl|PRINT USING}} "#####.## \\"; fq, note$
        {{Cl|PRINT USING}} {{Text|<nowiki>"#####.## \\"</nowiki>|#FFB100}}; fq, note$
    PlaySound fq
        {{Text|PlaySound|#55FF55}} fq
    {{Cl|IF...THEN|IF}} {{Cl|INKEY$}} > "" {{Cl|THEN}} {{Cl|EXIT DO}}
        {{Cl|IF}} {{Cl|INKEY$}} &gt; {{Text|<nowiki>""</nowiki>|#FFB100}} {{Cl|THEN}} {{Cl|EXIT DO}}
  {{Cl|NEXT}}
    {{Cl|NEXT}}
{{Cl|LOOP}}
{{Cl|LOOP}}
{{Cl|END}}
{{Cl|END}}


{{Cl|FUNCTION}} FreQ (octave, note, note$)
{{Cl|FUNCTION}} {{Text|FreQ|#55FF55}} (octave, note, note$)
FreQ = 440 * 2 ^ (octave + (note + 3) / 12 - 1) '* 12 note octave starts at C (3 notes up)
    {{Text|FreQ|#55FF55}} = {{Text|440|#F580B1}} * {{Text|2|#F580B1}} ^ (octave + (note + {{Text|3|#F580B1}}) / {{Text|12|#F580B1}} - {{Text|1|#F580B1}}) {{Text|<nowiki>'* 12 note octave starts at C (3 notes up)</nowiki>|#919191}}
note$ = {{Cl|MID$}}("C C#D D#E F F#G G#A A#B ", note * 2 + 1, 2)
    note$ = {{Cl|MID$ (function)|MID$}}({{Text|<nowiki>"C C#D D#E F F#G G#A A#B "</nowiki>|#FFB100}}, note * {{Text|2|#F580B1}} + {{Text|1|#F580B1}}, {{Text|2|#F580B1}})
{{Cl|END FUNCTION}}
{{Cl|END FUNCTION}}


{{Cl|SUB}} PlaySound (frq!)   ' plays sine wave fading in and out
{{Cl|SUB}} {{Text|PlaySound|#55FF55}} (frq!) {{Text|<nowiki>' plays sine wave fading in and out</nowiki>|#919191}}
SndLoop! = 0
    SndLoop! = {{Text|0|#F580B1}}
{{Cl|DO...LOOP|DO}} {{Cl|WHILE}} SndLoop! < rate&
    {{Cl|DO...LOOP|DO WHILE}} SndLoop! &lt; rate&
  {{Cl|_SNDRAW}} {{Cl|SIN}}((2 * 4 * {{Cl|ATN}}(1) * SndLoop! / rate&) * frq!) * {{Cl|EXP}}(-(SndLoop! / rate&) * 3)
        {{Cl|_SNDRAW}} {{Cl|SIN}}(({{Text|2|#F580B1}} * {{Text|4|#F580B1}} * {{Cl|ATN}}({{Text|1|#F580B1}}) * SndLoop! / rate&) * frq!) * {{Cl|EXP}}(-(SndLoop! / rate&) * {{Text|3|#F580B1}})
  SndLoop! = SndLoop! + 1
        SndLoop! = SndLoop! + {{Text|1|#F580B1}}
{{Cl|LOOP}}
    {{Cl|LOOP}}
{{Cl|_SNDRAWDONE}}
    {{Cl|_SNDRAWDONE}}
{{Cl|DO}}: {{Cl|LOOP}} {{Cl|WHILE}} {{Cl|_SNDRAWLEN}}  'flush the sound playing buffer
    {{Cl|DO}}: {{Cl|DO...LOOP|LOOP WHILE}} {{Cl|_SNDRAWLEN}} {{Text|<nowiki>'flush the sound playing buffer</nowiki>|#919191}}
{{Cl|END SUB}}
{{Cl|END SUB}}
{{CodeEnd}}
{{CodeEnd}}
Line 107: Line 120:


{{PageSeeAlso}}
{{PageSeeAlso}}
* [[_SNDRATE]], [[_SNDRAWLEN]]
* [[_SNDRAWBATCH]], [[_SNDRAWLEN]]
* [[_SNDOPENRAW]], [[_SNDRAWDONE]]
* [[_SNDOPENRAW]], [[_SNDRAWDONE]]
* [[_SNDOPEN]]
* [[_SNDOPEN]], [[_SNDRATE]]
* [[PLAY]], [[BEEP]]
* [[PLAY]], [[BEEP]]
* [[DTMF Phone Demo]]
* [[DTMF Phone Demo]]

Latest revision as of 13:29, 8 December 2024

The _SNDRAW statement plays sound wave sample frequencies created by a program.


Syntax

_SNDRAW leftSample[, rightSample][, pipeHandle&]


Parameters

  • The leftSample and rightSample value(s) can be any SINGLE or DOUBLE literal or variable frequency value from -1.0 to 1.0.
  • The pipeHandle& parameter refers to the sound pipe opened using _SNDOPENRAW.


Description

  • Specifying pipeHandle& allows sound to be played through two or more channels at the same time (version 1.000 and up).
  • If only leftSample value is used, the sound will come out of both speakers.
  • _SNDRAW is designed for continuous play. It will not produce any sound until a significant number of samples have been queued. No sound is played if only a few samples are queued.
  • Ensure that _SNDRAWLEN is comfortably above 0 (until you've finished playing sound). If you get occasional unintended random clicks, this generally means that _SNDRAWLEN has dropped to 0.
  • _SNDRAW is not intended to queue up many minutes worth of sound. It will probably work but will chew up a lot of memory (and if it gets swapped to disk, your sound could be interrupted abruptly).
  • _SNDRATE determines how many samples are played per second, but timing is done by the sound card, not your program.
  • Do not attempt to use _TIMER or _DELAY or _LIMIT to control the timing of _SNDRAW. You may use them for delays or to limit your program's CPU usage, but how much to queue should only be based on the _SNDRAWLEN.


Availability


Examples

Example 1
Sound using a sine wave with _SNDRAW Amplitude * SIN(8 * ATN(1) * Duration * (Frequency / _SNDRATE))
FREQ = 400 'any frequency desired from 36 to 10,000
Pi2 = 8 * ATN(1) '2 * pi
Amplitude = .3 'amplitude of the signal from -1.0 to 1.0
SampleRate = _SNDRATE 'sets the sample rate
FRate = FREQ / SampleRate '
FOR Duration = 0 TO 5 * SampleRate 'play 5 seconds
    _SNDRAW Amplitude * SIN(Pi2 * Duration * FRate) 'sine wave
    '_SNDRAW Amplitude * SGN(SIN(Pi2 * Duration * FRate))       'square wave
NEXT
_SNDRAWDONE
DO: LOOP WHILE _SNDRAWLEN
END
Code by DarthWho
Explanation: The loop Duration is determined by the number of seconds times the _SNDRATE number of samples per second. Square waves can use the same formula with Amplitude * SGN(SIN(8 * ATN(1) * Duration * (Frequency/_SNDRATE))).


Example 2
A simple ringing bell tone that tapers off.
t = 0
tmp$ = "Sample = ##.#####   Time = ##.#####"
LOCATE 1, 60: PRINT "Rate:"; _SNDRATE
DO
    'queue some sound
    DO WHILE _SNDRAWLEN < 0.2 'you may wish to adjust this
        sample = SIN(t * 440 * ATN(1) * 8) '440Hz sine wave (t * 440 * 2p)
        sample = sample * EXP(-t * 3) 'fade out eliminates clicks after sound
        _SNDRAW sample
        t = t + 1 / _SNDRATE 'sound card sample frequency determines time
    LOOP

    'do other stuff, but it may interrupt sound
    LOCATE 1, 1: PRINT USING tmp$; sample; t
LOOP WHILE t < 3.0 'play for 3 seconds

_SNDRAWDONE
DO WHILE _SNDRAWLEN > 0 'Finish any left over queued sound!
LOOP
END
Code by Artelius


Example 3
Routine uses _SNDRAW to display and play 12 notes from octaves 1 through 9.
DIM SHARED rate&
rate& = _SNDRATE
DO
    PRINT "Enter the octave 1 to 8 (0 quits!):";
    oct% = VAL(INPUT$(1)): PRINT oct%
    IF oct% = 0 THEN EXIT DO
    octave = oct% - 4 '440 is in the 4th octave, 9th note
    COLOR oct% + 1
    PRINT USING "Octave: ##"; oct%
    FOR Note = 0 TO 11 'notes C to B
        fq = FreQ(octave, Note, note$)
        PRINT USING "#####.## \\"; fq, note$
        PlaySound fq
        IF INKEY$ > "" THEN EXIT DO
    NEXT
LOOP
END

FUNCTION FreQ (octave, note, note$)
    FreQ = 440 * 2 ^ (octave + (note + 3) / 12 - 1) '* 12 note octave starts at C (3 notes up)
    note$ = MID$("C C#D D#E F F#G G#A A#B ", note * 2 + 1, 2)
END FUNCTION

SUB PlaySound (frq!) ' plays sine wave fading in and out
    SndLoop! = 0
    DO WHILE SndLoop! < rate&
        _SNDRAW SIN((2 * 4 * ATN(1) * SndLoop! / rate&) * frq!) * EXP(-(SndLoop! / rate&) * 3)
        SndLoop! = SndLoop! + 1
    LOOP
    _SNDRAWDONE
    DO: LOOP WHILE _SNDRAWLEN 'flush the sound playing buffer
END SUB
Code by CodeGuy


See also



Navigation:
Main Page with Articles and Tutorials
Keyword Reference - Alphabetical
Keyword Reference - By usage
Report a broken link