SFML community forums
Help => Audio => Topic started by: Notnasiul on July 25, 2011, 01:01:30 pm
-
Has anyone done this? I'm starting with SFML, so I'm still pretty lost. I found this basic effect generator http://www.sfml-dev.org/forum/viewtopic.php?t=3449&highlight=soundman which is great for precise sound effects, but I need something that creates a continuous sound. That is, an oscillator.
I guess I have to fill a soundbuffer with the right samples (using a sine wave, knowing the target frequency and amplitude), feed it to a sound object and play it. But I must be doing something wrong... Just as a test I did this:
#include <SFML/Audio.hpp>
#include "math.h"
int main()
{
int nSamples = 10000; // How many samples do I need for a cycle?
sf::Int16 samples[nSamples];
sf::SoundBuffer buffer;
sf::Sound sound;
//Fill samples with a pure A tone (440hrz)
for (int i = 0; i < nSamples ; i++) {
samples[i] = ( sin(440.0f * (2.0f * 3.1415f) * i / 44100));
}
bool ok = buffer.LoadFromSamples(samples, nSamples , 1, 44100);
if (!ok) exit(-1);
sound.SetBuffer(buffer);
sound.Play();
sf::Sleep(5.0f);
return 0;
}
Nothing is heard when executed...
-
std::sin() returns values in [-1,1]. If you use sf::Int16, you probably want to scale the samples.
By the way, you should avoid std::exit(), as it doesn't call destructors an thus doesn't clean up correctly. And use <cmath> instead of <math.h>. Apart from that, the following code is not standard-conforming. You should use const int nSamples for portable code.
int nSamples = 10000; // How many samples do I need for a cycle?
sf::Int16 samples[nSamples];
-
Right, and I guess that scale corresponds to the amplitude. It works.
Now, using Loop that sound will play forever, even in background (great!). And this is where I'm not sure whether I have to use a soundbuffer or a soundstream...
Say I created those samples at 440Hrz, but now I want to change their frequency to 880Hrz. If I update the samples vector, reload them in the soundbuffer and reasign this soundbuffer to the current sound, it will simply ignore me and keep playing the previous frequency. That's where I guess a soundstream will be handy: I just would feed it with new samples at 880.
I don't know, that may be a complete nonsense. The question would be: how would I change a sound's buffer samples while it's playing?
This post seems to be related: http://www.sfml-dev.org/forum/viewtopic.php?t=3929&postdays=0&postorder=asc&start=0, I'll read it ;)
-
The question would be: how would I change a sound's buffer samples while it's playing?
If the obvious way doesn't work, it might be a bug in SFML. Can you please provide a complete and minimal source code that reproduces this problem?
-
Ok, let's see...
Oscillator.h
#ifndef __OSCILLATOR__
#define __OSCILLATOR__
#include <SFML/Audio.hpp>
#include <iostream>
#include <math.h>
#define NSAMPLES 44100
class Oscillator
{
public :
Oscillator (float frequency, float amplitude);
void setTone(float frequency, float amplitude);
private :
sf::SoundBuffer buffer;
sf::Sound sound;
sf::Int16 samples[NSAMPLES];
};
#endif
Oscillator.cpp
#include "Oscillator.h"
Oscillator::Oscillator(float frequency, float amplitude) {
setTone( frequency, amplitude);
sound.SetLoop(true);
sound.Play();
}
void Oscillator::setTone(float frequency, float amplitude) {
for (int i = 0; i < NSAMPLES; i++) {
samples[i] = ( amplitude * sin(frequency * (2.0f * 3.1415f) * i / 44100));
}
buffer.LoadFromSamples(samples, NSAMPLES, 1, 44100);
sound.SetBuffer(buffer);
}
main.cpp
#include <SFML/Audio.hpp>
#include "Oscillator.h"
int main() {
Oscillator *o = new Oscillator(440, 10000);
sf::Sleep(2.0f);
o->setTone(880,10000); // but we still hear 440 after this...
sf::Sleep(2.0f);
return 0;
}
SetTone works the first time it's called, in the constructor. But samples won't change the second time it's called, after two seconds.
EDIT: I guess this is not the right way of doing this. I should have a look at soundstream...
-
Ok thanks, I'll test this as soon as possible.
By the way, which version of SFML do you use?
-
Sorry, still with 1.6. I know you told me to switch to 2.0, but I did not manage to prepare it with cmake for codeblocks. That's in my todo list :(
-
Could anyone try this or was I punished for working with 1.6? :D
-
Could anyone try this or was I punished for working with 1.6?
Kind of :D
I'm not working on 1.6 anymore, so I won't test until you try first with SFML 2.
Plus... I still have no audio (I can't find a Windows 7 x64 driver for my audio chipset), so I will definitely not be able to test this :?
-
lol, ok, I'll try SFML 2.0, although compiling it is being a hell! (well, it did compile with Visual Studio express edition 2008, but now I'm getting lots of undefined references on my application... so still trying to link everything correctly!)
-
If you link SFML statically, don't forget to define SFML_STATIC in your preprocessor defines.