What exactly does SetSoundFrequency() ???

Just starting out? Need help? Post your questions and find answers here.
infratec
Always Here
Always Here
Posts: 7625
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

What exactly does SetSoundFrequency() ???

Post by infratec »

Hi,

want to write an emulator for an 'phasewheel' which delivers the rpm and the position of cylinders to the ECU.
The wheel has many teeth with a few missing to show a special position.

My idea was to create a sound with this as waveform. So far so good.
Now I want to setup different speeds.
I thought it is possible with SetSoundFrequency().
But I don't know what it does.
The second parameter is definately not the frequency.

An example:

Code: Select all

EnableExplicit

Structure RIFFStructure
  Riff.s{4}
  Length.l
  Wave.s{4}
EndStructure


Structure fmtStructure
  fmt.s{4}
  Length.l
  Format.u
  Channels.u
  SampleRate.l
  BytesPerSecond.l
  BlockAlign.u
  BitsPerSample.u
EndStructure


Structure dataStructure
  Signature.s{4}
  Length.l
EndStructure



Procedure.i CreateSineWAV(*WAVBuffer)
  
  Protected.i Result, dataOffset, Ptr, i
  Protected *RiffPtr.RIFFStructure, *fmtPtr.fmtStructure, *dataPtr.dataStructure
  
  If *WAVBuffer
    
    *RiffPtr = *WAVBuffer
    *RiffPtr\Riff = "RIFF"
    *RiffPtr\Wave = "WAVE"
    
    *fmtPtr = *WAVBuffer + SizeOf(RIFFStructure)
    *fmtPtr\fmt = "fmt "
    *fmtPtr\Length = SizeOf(fmtStructure) - 8
    *fmtPtr\Format = 1
    *fmtPtr\Channels = 1
    *fmtPtr\SampleRate = 44100
    *fmtPtr\BitsPerSample = 16
    *fmtPtr\BlockAlign = *fmtPtr\Channels * ((*fmtPtr\BitsPerSample + 7) / 8)
    *fmtPtr\BytesPerSecond = *fmtPtr\SampleRate * *fmtPtr\BlockAlign
    
    
    *dataPtr = *WAVBuffer + SizeOf(RIFFStructure) + SizeOf(fmtStructure)
    *dataPtr\Signature = "data"
    
    dataOffset = SizeOf(RIFFStructure) + SizeOf(fmtStructure) + SizeOf(dataStructure)
    
    Ptr = 0
    For i = 0 To 359
      PokeW(*WAVBuffer + dataOffset + Ptr, Sin(Radian(i)) * 30000)
      Ptr + 2
    Next i
    
    *dataPtr\Length = Ptr
    *RiffPtr\Length = SizeOf(RIFFStructure) + SizeOf(fmtStructure) + SizeOf(dataStructure) + Ptr - 8
    
    ;ShowMemoryViewer(*WAVBuffer, *RiffPtr\Length + 8)
    
    Result = #True
    
  EndIf
  
  ProcedureReturn Result
  
EndProcedure


InitSound()

Define *Buffer

*Buffer = AllocateMemory(1024)
If *Buffer
  
  If CreateSineWAV(*Buffer)
    Debug "Created"
    If CatchSound(0, *Buffer)
      
      Debug "Play"
      PlaySound(0, #PB_Sound_Loop)
      Delay(3000)
      
      Debug "Play 44100"
      SetSoundFrequency(0, 44100)
      Delay(3000)
      
    EndIf
  EndIf
  
  FreeMemory(*Buffer)
EndIf
If you check the created WAV with audacity for example, you see one sine wave with 125Hz.
That's also what you can hear during the first 3 seconds.

Than I tried to use SetSoundFrequency()...
Not really successfull.
If I use the samplerate as 'frequency', than I see and hear the same sound.

Can anyone explain what exactly SetSoundFrequency() does?

Or is it a bug?

Bernd

P.S.: disable 'create unicode executable' in compiler options!
Pot Noodle
Enthusiast
Enthusiast
Posts: 202
Joined: Sat Feb 18, 2012 10:21 pm
Location: Leicestershire

Re: What exactly does SetSoundFrequency() ???

Post by Pot Noodle »

Hi Infratec,

I used SetSoundFrequency() in my car game for the engine sound.
Increasing the frequency and then changing gear and so on.

Take a look at this it may just answer you question.

http://forum.purebasic.com/english/view ... 7ca9bc1877

Hope it helps. :wink:
P.N.
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: What exactly does SetSoundFrequency() ???

Post by BasicallyPure »

From my experience with SetSoundFrequency() I have come to this conclusion.
When you specify the frequency parameter you are setting the sample rate for the sound playback.
It is useful to know the sample rate of the original sound that you are playing.
For example assume the original sound was a 1000 Hz waveform created with a sample rate of 44100 samples per second.
If you use SetSoundFrequency(44100) before playback then the pitch of the sound will be the same as the original (1000 Hz).
If you were to use SetSoundFrequency(22050) then the pitch would be 1/2 of the original (500 Hz).

PlaybackFrequency = OriginalFrequency * SetFrequency / OriginalSampleRate
PlaybackFrequency = 1000 * 22050 / 44100 = 500

BP
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
infratec
Always Here
Always Here
Posts: 7625
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: What exactly does SetSoundFrequency() ???

Post by infratec »

@BasicallyPure

That's also what I thought.

From Audacity samplerates reaches from 8000 to 384000Hz.
Now I have to check if each 'frequency' (new samplerate) between is possible.

Bernd
infratec
Always Here
Always Here
Posts: 7625
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: What exactly does SetSoundFrequency() ???

Post by infratec »

Hi,

in my test I can set at maximum 200000 as 'frequency'

Code: Select all

Procedure NewSetSoundFrequency(Sound.i, OrgSamplerate.i, OrgFreq.i, NewFreq.i)
  
  SetSoundFrequency(Sound, NewFreq * OrgSamplerate / OrgFreq)
  
EndProcedure
And the OrgSamplerate and OrgFreq values are always the original values :!:

That means that PB (or windows) stores this values somewhere.

This works:

Code: Select all

PlaySound(0, #PB_Sound_Loop)
Delay(3000)

NewSetSoundFrequency(0, 44100, 125, 250)
Delay(3000)

NewSetSoundFrequency(0, 44100, 125, 125)
Delay(3000)
more or less exact:
234Hz instead of 250.

Bernd
Pot Noodle
Enthusiast
Enthusiast
Posts: 202
Joined: Sat Feb 18, 2012 10:21 pm
Location: Leicestershire

Re: What exactly does SetSoundFrequency() ???

Post by Pot Noodle »

Thanks BasicallyPure

You explained it better than I could :wink:
P.N.
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: What exactly does SetSoundFrequency() ???

Post by BasicallyPure »

@infratec

looking at the code from the first post it looks like the frequency produced is
44100 / 360 = 122.5 Hz.
If you change the value 125 to 122.5 your results may be more accurate.
Also, using floats for frequencies may work better.

Code: Select all

Procedure NewSetSoundFrequency(Sound.i, OrgSamplerate.i, OrgFreq.f, NewFreq.f)
  
  SetSoundFrequency(Sound, NewFreq * OrgSamplerate / OrgFreq)
  
EndProcedure

Code: Select all

PlaySound(0, #PB_Sound_Loop)
Delay(3000)

NewSetSoundFrequency(0, 44100, 122.5, 250) ; sample rate = 90000
Delay(3000)

NewSetSoundFrequency(0, 44100, 122.5, 125) ; sample rate = 45000
Delay(3000)

NewSetSoundFrequency(0, 44100, 122.5, 122.5) ; sample rate = 44100
Delay(3000)
BP
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
Post Reply