Homebrew Wav Streaming: some technical helps needed

Rinnegatamante

Well-Known Member
OP
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
Hi, i'm writing a function to stream a wav file (so i can reduce RAM usage for Wav reproduction) but i'm not very expert about samplerate and bps.

If i know:
- Current time passed from wav starts in millisecond
- Wav samplerate
- Wav bytepersample (BlockAlign voice in header)
- Audiobuffer size

How can i find how much bytes have been read from audio buffer?

For example, if i heard 20 seconds of an audiobuffer at 44100HZ Samplerate for a Wav with 16 Bitpersample Stereo (so Bytepersample = 4) with PCM16 Codec, how many bytes from my audiobuffer have been processed by CSND_playsound?
 

Rinnegatamante

Well-Known Member
OP
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
Thanks for the link, i wrote the correct condition check i think but now i'm having some issues with buffer updating. Is it possible tu update only a part of a buffer when playsound is processing it?

I wrote a thing like this, but it seems the function jumps directly from first loaded block to the final block of the wav file (without processing the middle part of the file):

Code:
static int lua_streamWav(lua_State *L)
{
    int argc = lua_gettop(L);
    if (argc != 1) return luaL_error(L, "wrong number of arguments");
    wav* src = (wav*)luaL_checkint(L, 1);
    if (((src->samplerate * src->bytepersample * ((osGetTime() - src->tick) / 1000)) > ((src->mem_size / 2) * src->moltiplier) && (src->isPlaying)){
        if ((src->moltiplier % 2) == 1){
            u32 bytesRead;
            //Update and flush first half-buffer
            if (src->audiobuf2 == NULL){
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size)*(src->moltiplier), src->audiobuf, (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                GSPGPU_FlushDataCache(NULL, src->audiobuf, (src->mem_size)/2);
            }else{
                u8* tmp_buffer = (u8*)linearAlloc((src->mem_size)/2);
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size)*(src->moltiplier), tmp_buffer, (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                u32 size_tbp = (src->mem_size)/2;
                u32 off=0;
                u32 i=0;
                u16 z;
                while (i < size_tbp){
                    z=0;
                    while (z < (src->bytepersample/2)){
                        src->audiobuf[off+z] = tmp_buffer[i+z];
                        src->audiobuf2[off+z] = tmp_buffer[i+z+(src->bytepersample/2)];
                        z++;
                    }
                    z=0;
                    i=i+src->bytepersample;
                    off=off+(src->bytepersample/2);
                }
                linearFree(tmp_buffer);
                GSPGPU_FlushDataCache(NULL, src->audiobuf, (src->mem_size)/4);
                GSPGPU_FlushDataCache(NULL, src->audiobuf2, (src->mem_size)/4);
            }
        }else{
            u32 bytesRead;
            //Update and flush second half-buffer
            if (src->audiobuf2 == NULL){
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size)*(src->moltiplier), src->audiobuf+((src->mem_size)/2), (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                GSPGPU_FlushDataCache(NULL, src->audiobuf+((src->mem_size)/2), (src->mem_size)/2);
            }else{
                u8* tmp_buffer = (u8*)linearAlloc((src->mem_size)/2);
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size)*(src->moltiplier), tmp_buffer, (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                u32 size_tbp = (src->mem_size)/2;
                u32 off=0;
                u32 i=0;
                u16 z;
                while (i < size_tbp){
                    z=0;
                    while (z < (src->bytepersample/2)){
                        src->audiobuf[(src->mem_size)/2+off+z] = tmp_buffer[i+z];
                        src->audiobuf2[(src->mem_size)/2+off+z] = tmp_buffer[i+z+(src->bytepersample/2)];
                        z++;
                    }
                i=i+src->bytepersample;
                off=off+(src->bytepersample/2);
                }
                linearFree(tmp_buffer);
                GSPGPU_FlushDataCache(NULL, src->audiobuf+((src->mem_size)/2), (src->mem_size)/4);
                GSPGPU_FlushDataCache(NULL, src->audiobuf2+((src->mem_size)/2), (src->mem_size)/4);
            }
        }
    }
    return 0;
}
 

Rinnegatamante

Well-Known Member
OP
Member
Joined
Nov 24, 2014
Messages
3,162
Trophies
2
Age
29
Location
Bologna
Website
rinnegatamante.it
XP
4,857
Country
Italy
It seems the problem is here:

(src->samplerate * src->bytepersample * ((osGetTime() - src->tick) / 1000)

I tried to return this value for debug and i get a thing like this:

0 second: 0
1 second: 17k
2 seconds: 34k
3 seconds: 51k
4 seconds: 7 * 10^18 (O.o)

Where src->samplerate is 44100
src->bytepersample is 4
src->tick is the osGetTime result of the start wav

P.S. Solved recompiling libctru (O.o), finished also streaming functions both mono and stereo sounds (i must add only restart for looping music and stop for no looping music at streaming end.).

If someone is interested, here's the code:
Code:
int lua_streamWav(lua_State *L)
{
    int argc = lua_gettop(L);
    if (argc != 1) return luaL_error(L, "wrong number of arguments");
    wav* src = (wav*)luaL_checkint(L, 1);
    u32 size;
    if (((src->samplerate * src->bytepersample * ((osGetTime() - src->tick) / 1000)) > ((src->mem_size / 2) * src->moltiplier)) && (src->isPlaying)){
        if ((src->moltiplier % 2) == 1){
            u32 bytesRead;
            //Update and flush first half-buffer
            if (src->audiobuf2 == NULL){
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(((src->mem_size)/2)*(src->moltiplier + 1)), src->audiobuf, (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                GSPGPU_FlushDataCache(NULL, src->audiobuf, src->mem_size);
            }else{
                u8* tmp_buffer = (u8*)linearAlloc((src->mem_size)/2);
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size/2)*(src->moltiplier + 1), tmp_buffer, (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                u32 size_tbp = (src->mem_size)/2;
                u32 off=0;
                u32 i=0;
                u16 z;
                while (i < size_tbp){
                    z=0;
                    while (z < (src->bytepersample/2)){
                        src->audiobuf[off+z] = tmp_buffer[i+z];
                        src->audiobuf2[off+z] = tmp_buffer[i+z+(src->bytepersample/2)];
                        z++;
                    }
                    z=0;
                    i=i+src->bytepersample;
                    off=off+(src->bytepersample/2);
                }
                linearFree(tmp_buffer);
            GSPGPU_FlushDataCache(NULL, src->audiobuf, (src->mem_size)/2);
            GSPGPU_FlushDataCache(NULL, src->audiobuf2, (src->mem_size)/2);
            }
        }else{
            u32 bytesRead;
            //Update and flush second half-buffer
            if (src->audiobuf2 == NULL){
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(((src->mem_size)/2)*(src->moltiplier + 1)), src->audiobuf+((src->mem_size)/2), (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                GSPGPU_FlushDataCache(NULL, src->audiobuf, src->mem_size);
            }else{
                u8* tmp_buffer = (u8*)linearAlloc((src->mem_size)/2);
                FSFILE_Read(src->sourceFile, &bytesRead, src->startRead+(src->mem_size/2)*(src->moltiplier + 1), tmp_buffer, (src->mem_size)/2);
                src->moltiplier = src->moltiplier + 1;
                u32 size_tbp = (src->mem_size)/2;
                u32 off=0;
                u32 i=0;
                u16 z;
                while (i < size_tbp){
                    z=0;
                    while (z < (src->bytepersample/2)){
                        src->audiobuf[(src->mem_size)/4+off+z] = tmp_buffer[i+z];
                        src->audiobuf2[(src->mem_size)/4+off+z] = tmp_buffer[i+z+(src->bytepersample/2)];
                        z++;
                    }
                i=i+src->bytepersample;
                off=off+(src->bytepersample/2);
                }
                linearFree(tmp_buffer);
                GSPGPU_FlushDataCache(NULL, src->audiobuf, (src->mem_size)/2);
                GSPGPU_FlushDataCache(NULL, src->audiobuf2, (src->mem_size)/2);
            }
        }
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    HiradeGirl @ HiradeGirl: Wlak like a Wlaker