Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Getting samples with no delay  (Read 3715 times)

0 Members and 1 Guest are viewing this topic.

Irbis

  • Newbie
  • *
  • Posts: 7
    • View Profile
Getting samples with no delay
« on: January 15, 2011, 07:44:28 pm »
Greetings, ladies and gentlemen.
I'm doing a project that requires a real-time spectrum visualization.
So, the algorithm looks like this:
1. Get playing offset
2. Get small amount of samples starting from that offset
3. Use FFT on those samples
4. Visualize

That's the code that I'm using for it:


Code: [Select]

sf::SoundBuffer SB;
SB.LoadFromFile("file.ogg");

const sf::Int16 * SBp;
SBp = SB.GetSamples();

sf::Sound SND;
SND.SetBuffer(SB);

SND.Play();

//Get current offset
//Fill an FFT input array with some amount of samples starting from that offset
//Call FFTW


The problem is that loading from file into the sound buffer takes some  time because it loads the whole file. I don't need the whole file at any moment, only small chunks.

Is it possible to load files chunk by chunk and get samples from those chunks without waiting for the whole file to load? As I understand sf::Music is doing the loading that way, but it doesn't allow me to get it's buffer.
Code: [Select]

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Getting samples with no delay
« Reply #1 on: January 15, 2011, 07:48:00 pm »
Maybe sf::SoundStream is something for you?

By the way:
Code: [Select]
const sf::SoundBuffer * SB;
SB.LoadFromFile("file.ogg");
I really doubt that this is your actual code. There are two compiletime errors and undefined behaviour at runtime. ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Irbis

  • Newbie
  • *
  • Posts: 7
    • View Profile
Getting samples with no delay
« Reply #2 on: January 15, 2011, 07:57:56 pm »
Quote from: "Nexus"
Maybe sf::SoundStream is something for you?


Maybe I'm blind, but I wasn't able to find the solution to do this using SoundStream. Is it really possible to get samples from it? If so I'll try to read documentation about it once again and don't bother people with obvious questions;)

upd: Okay, after reading the SoundStream tutorial I can imagine how to get samples from SoundStream, but I don't see a way to get them while loading chunk by chunk, because it does the same thing - loads a file into the SoundBuffer in a memory first.

Quote from: "Nexus"

By the way:
Code: [Select]
const sf::SoundBuffer * SB;
SB.LoadFromFile("file.ogg");
I really doubt that this is your actual code. There are two compiletime errors and undefined behaviour at runtime. ;)


That's a typo, copypasted some messy code, already changed it.

Irbis

  • Newbie
  • *
  • Posts: 7
    • View Profile
Getting samples with no delay
« Reply #3 on: January 16, 2011, 01:04:31 am »
Okay, I wasn't able to find how to do this using only SFML, but I've written the workaround that combines code from the SoundStream tutorial and some libsndfile code. Maybe it'll be useful for someone:

SequentialSoundStreamer.hpp
Code: [Select]

#include <SFML/Audio.hpp>
#include <sndfile.h>
#include <fftw3.h>
#include <iostream>

namespace sfe
{

class SequentialSoundStreamer : public sf::SoundStream
{
public :
    SequentialSoundStreamer(std::size_t BufferSize) :
    myBufferSize(BufferSize)  {}
    bool Open(const char * Filename);

private :
    virtual bool OnGetData(sf::SoundStream::Chunk& Data);
    std::size_t            myBufferSize;

    SNDFILE * SoundFile;
    SF_INFO SoundFileInfo;
    short * SamplesArray;
};
}


SequentialSoundStreamer.cpp
Code: [Select]

#include "SequentialSoundStreamer.hpp"

namespace sfe
{
    bool SequentialSoundStreamer::Open(const char * Filename)
    {
        SoundFileInfo.format=0;
        if (!(SoundFile = sf_open (Filename, SFM_READ, &SoundFileInfo)))
            std::cout<<"\nCan't open the file.\n";

        Initialize(SoundFileInfo.channels,SoundFileInfo.samplerate);

        SamplesArray = (short*) fftw_malloc(sizeof(short) * myBufferSize);

        return false;
    }

    bool SequentialSoundStreamer::OnGetData(sf::SoundStream::Chunk& Data)
    {
        if (! (Data.NbSamples = sf_readf_short (SoundFile, SamplesArray, myBufferSize / SoundFileInfo.channels) * SoundFileInfo.channels))
           {std::cout<<"\nCan't read the file (can be the end of it).\n"; return false;}

        Data.Samples   = SamplesArray;

        return true;
    }

}


As sound is being loaded chunk by chunk these chunks (SamplesArray) can be passed whatever they needed to.
malloc can be used instead of fftw_malloc.

Jeffs

  • Newbie
  • *
  • Posts: 4
    • View Profile
Getting samples with no delay
« Reply #4 on: March 20, 2011, 12:22:37 pm »
That's funny, I'm working on almost the exact same project, and I have almost the exact same problem. I'll look into the solution you found! Thanks.