SFML community forums
Help => Audio => Topic started by: TheMagicNumber on December 31, 2010, 07:38:59 am
-
I'm playing around with SoundStreams and I can't seem to get this to stop repeating samples.
Here's my code right now (it's not a lot!): http://dl.dropbox.com/u/675786/SoundTest.zip
-
Can you post a minimal and complete piece of code, directly on the forum please? It's a lot more convenient for us than to download and extract an archive, then figuring out which part of the code is relevant ;)
-
main.cpp
#include <iostream>
#include <SoundPlayer.hpp>
const int sampleRate = 8000;
const int sampleRate2 = sampleRate / 2;
int main()
{
sf::Int16 b[sampleRate2];
SoundPlayer s(sampleRate);
s.Start();
double amplitude = 0.5 * 0xFFFF;
double frequency = 200;
char res = 0;
while (s.GetStatus() == s.Playing)
{
sf::Sleep(0.15f);
std::cout << "Press enter to add more samples." << std::endl;
std::cin.get(res);
if (res != '\n')
break;
for (int i = 0; i < sampleRate2; i++)
b[i] = (short)(amplitude * sin((2 * 3.14159 * i * frequency) / sampleRate));
frequency += 25;
s.Add(b, sampleRate2);
}
s.End();
return 0;
}
SoundPlayer.hpp
#pragma once
#include <iterator>
#include <SFML/Audio.hpp>
class SoundPlayer : public sf::SoundStream
{
sf::Mutex mutex; // for buffer
std::vector<sf::Int16> buffer;
std::vector<sf::Int16> playingBuffer;
size_t offset;
bool playing;
virtual bool OnGetData(sf::SoundStream::Chunk& data);
virtual void OnSeek(float timeOffset);
public:
SoundPlayer(int sampleRate);
~SoundPlayer();
void Start();
void End();
void Add(sf::Int16* data, size_t count);
};
SoundPlayer.cpp
#include <SoundPlayer.hpp>
SoundPlayer::SoundPlayer(int sampleRate)
: playing(false)
{
Initialize(1, sampleRate);
SetLoop(false);
}
SoundPlayer::~SoundPlayer()
{
End();
}
void SoundPlayer::Start()
{
if (playing)
return;
playing = true;
Play();
}
void SoundPlayer::End()
{
if (!playing)
return;
playing = false;
Stop();
}
void SoundPlayer::Add(sf::Int16* data, size_t count)
{
sf::Lock lock(mutex);
std::copy(data, data + count, std::back_inserter(buffer));
}
bool SoundPlayer::OnGetData(sf::SoundStream::Chunk& data)
{
if (!playing)
return false;
while (!buffer.size() && playing)
sf::Sleep(0.01f);
{
sf::Lock lock(mutex);
playingBuffer.assign(buffer.begin(), buffer.end());
buffer.clear();
}
if (!playingBuffer.size())
return false;
data.Samples = &playingBuffer[0];
data.NbSamples = playingBuffer.size();
return true;
}
void SoundPlayer::OnSeek(float timeOffset)
{
}
-
I don't see anything wrong. I'll try to test your code.
-
Thanks.
Also, is there any way to make it start immediately, or will it wait for enough samples to start playing?
-
When you call Play(), the stream tries to fill all its internal buffers by calling OnGetData, before actually starting playback. So it will start playing immediately if your have sample data available at the moment you call Play().
-
Okay, so it plays when it has enough sound data. Could this be related to why it repeats?
-
I don't know. Have you tried calling Add() before Start()?
-
Yes, same result.
It only repeats if it had to wait on samples to continue playing. I would really like to have it do that without the repeating.
-
Donno if this is your problem but it's a big NONO if I get it right...
while (!buffer.size() && playing)
sf::Sleep(0.01f);
{
sf::Lock lock(mutex);
playingBuffer.assign(buffer.begin(), buffer.end());
buffer.clear();
}
In this part of the code you only loop the sf::Sleep until the loop returns false. Then you enter a local-scope which does what I think you wanted the loop to do.
*EDIT*
No nevermind, the scope-params threw me off, that's not the issue