Loading and Playing Wav, problem in Wii

support for the powerpc toolchain
Post Reply
the_marioga
Posts: 7
Joined: Wed Sep 29, 2010 12:06 pm

Loading and Playing Wav, problem in Wii

Post by the_marioga » Wed Sep 29, 2010 12:08 pm

Hi, see if you can help me, I need to load and play WAV files, but the load function and extracts the header and maybe shoot me a code dump to try, then see if you can lend a hand. (SDL serves me no) (Google Translate)

Dump code files:


Wavplayer.cpp

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "wavplayer.h"

#define IS_BIG_ENDIAN       1

#define MIN(a,b)  ((a) > (b) ? (b) : (a))
#define MAX(a,b)  ((a) < (b) ? (b) : (a))

#define GET3BYTES(p)    ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16))

#define SWAP16(x)\
    ((u16)((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8)))

#define SWAP32(x)\
    ((u32)((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | \
     (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24)))

typedef unsigned int        u32;  
typedef unsigned short int  u16; 

#if IS_BIG_ENDIAN
    #define SWAP_ED16(x)    SWAP16(x)
    #define SWAP_ED32(x)    SWAP32(x)
    #define SAMP_ENDIAN     (u16(2))
#else
    #define SWAP_ED16(x)    (x)
    #define SWAP_ED32(x)    (x)
    #define SAMP_ENDIAN     (u16(1))
#endif

void ReverseEndian(void* buffer, int byteWidth, int frames)
{
    switch (byteWidth)
    {
    case 2 :
        {
            u16* pusBuf  = (u16*)buffer;
            for (int i = 0; i < frames; i++) 
            {
                pusBuf[i] = SWAP16(pusBuf[i]);
            }
            break;
        }
    case 3 :
        {
            char* a = (char*)buffer;
            char c; 
            while(--frames >= 0)
            {
                c = a[0];
                a[0] = a[2];
                a[2] = c;
                a += 3;
            }
            break;
        }
    case 4 :
        {
            u32* puiBuf  = (u32*)buffer;
            for (int i = 0; i < frames; i++) 
            {
                puiBuf[i] = SWAP32(puiBuf[i]);
            }
            break;
        }
    default:
        break;
    }
}

int ReadFile( FILE* fd, void *buf, int n, int offset = 0)
{
    if (offset != 0) fseek(fd, offset, SEEK_CUR);
    int readlen = (int)fread(buf, 1, n, fd); 
    return readlen;
}

int CloseFile( FILE* fd)
{
    return fclose(fd); 
}

#define VERIFY_CHUNKID(fd, id, len) \
{   \
    char chunkID[(len)+1];  \
    ReadFile((fd), chunkID, (len));   chunkID[(len)] = char(0); \
    if ( strncmp(&chunkID[0], (id), (len)) )    \
    {   \
        return -1;  \
    }   \
}   
#define LOAD_2BYTES(fd, x)  \
{   \
    ReadFile((fd), &(x), 2);   \
    (x) = SWAP_ED16(x);   \
}
#define LOAD_4BYTES(fd, x)  \
{   \
    ReadFile((fd), &(x), 4);   \
    (x) = SWAP_ED32(x);   \
}

static int _load_pcmwavfmt(FILE* fd, PCMWAVFmt* pFmt)
{
    u32    chunkSize, samplesPerSec, bytesPerSec;
    u16  waveFmtType, channel, blockSize, bitsPerSample;

    VERIFY_CHUNKID(fd, "RIFF", 4);
    LOAD_4BYTES(fd, chunkSize);
    VERIFY_CHUNKID(fd, "WAVEfmt ", 8);
    LOAD_4BYTES(fd, chunkSize);
    LOAD_2BYTES(fd, waveFmtType);
    LOAD_2BYTES(fd, channel);
    LOAD_4BYTES(fd, samplesPerSec);
    LOAD_4BYTES(fd, bytesPerSec);
    LOAD_2BYTES(fd, blockSize);
    LOAD_2BYTES(fd, bitsPerSample);
    VERIFY_CHUNKID(fd, "data", 4);
    LOAD_4BYTES(fd, chunkSize);

    pFmt->sample_rate   = samplesPerSec;
    pFmt->sample_byte   = blockSize/channel;
    pFmt->sample_bit    = bitsPerSample;
    pFmt->sample_count  = chunkSize/blockSize;
    pFmt->sample_channel= channel;
    pFmt->sample_format = waveFmtType;
    return 0;
}

void* LoadPCMWav(const char* file, PCMWAVFmt* pFmt) {
    FILE* fd;
    if (!(fd = fopen(file, "rb"))) {
        return NULL;
    }
    if (_load_pcmwavfmt(fd,pFmt)) {
        CloseFile(fd);
        return NULL;
    }
    //check the wavefile length
    int iLen;
    if ((fseek(fd, 0, SEEK_END)!=0) || ((iLen = ftell(fd))<0) || (fseek(fd, 44L, SEEK_SET)!=0) ) {
        CloseFile(fd);
        return NULL;
    }
    iLen -= 44;

    int wavlen = pFmt->sample_byte*pFmt->sample_count*pFmt->sample_channel;
    if (iLen != wavlen)
    {
        CloseFile(fd);
        return NULL;
    }
    u32 stFrame = (pFmt->start != PCMClock(-1)) ? PCMClock2Frame(pFmt->start, pFmt->sample_rate) : 0;
    u32 enFrame = (pFmt->end   != PCMClock(-1)) ? PCMClock2Frame(pFmt->end  , pFmt->sample_rate) : pFmt->sample_count;
    enFrame = MIN(enFrame, pFmt->sample_count);
    stFrame = MIN(stFrame, enFrame);
    u32 npad = enFrame - stFrame; 
    if ( npad <= 0 )
    {
        CloseFile(fd);
        return NULL;
    }
    int vecSize = pFmt->sample_byte*pFmt->sample_channel;
    int offset = stFrame * vecSize;
    void* pWav = (void*)memalign(128, npad*vecSize);

    u32 readlen = ReadFile(fd, pWav, npad*vecSize, offset);
    if (readlen != npad*vecSize)
    {
        CloseFile(fd);
        free(pWav);
        return NULL;
    }
    if (pFmt->sample_format != SAMP_ENDIAN)
    {
        ReverseEndian(pWav, pFmt->sample_byte, pFmt->sample_count*pFmt->sample_channel);
    } 
    pFmt->sample_format = SAMP_ENDIAN;
    pFmt->sample_count  = npad;
    return pWav;
}
Wavplayer.h

Code: Select all

#ifndef _PCMWAVFILE_H
#define _PCMWAVFILE_H

typedef unsigned long long	PCMClock;

typedef struct _PCMWAVFmt {
    unsigned int    sample_rate;    /* Sample frequency                 */
    unsigned short  sample_byte;    /* number of bytes per sample       */
    unsigned short  sample_bit;     /* number of valid bits per sample  */
    unsigned int    sample_count;   /* number of samples                */
    unsigned short  sample_channel; /* number of channels per sample    */
    unsigned short  sample_format;  /* little-endian(1), big-endian(2)  */
    PCMClock start, end;            /* start/end time in 100ns          */
}PCMWAVFmt;

#define PCMClock2Frame(clock, samprate) \
    ((unsigned int)(PCMClock(samprate)*(clock)/PCMClock(10000000)))

#define Frame2PCMClock(frame, samprate) \
        (PCMClock(frame)*PCMClock(10000000)/PCMClock(samprate))

#if defined(__LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)
extern "C" {
#endif

void* LoadPCMWav(const char* file, PCMWAVFmt* pFmt);

#if defined(__LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)
}
#endif
#endif // _PCMWAVFILE_H
Luego lo uso asi:

Code: Select all

	PCMWAVFmt* pFmt;
int wavPlay(const char* file) {
	void *buf = LoadPCMWav(file, pFmt);
	if (buf) {
		ASND_SetVoice(ASND_GetFirstUnusedVoice(), VOICE_STEREO_16BIT, 8000,0, buf, sizeof(buf), 255, 255, NULL);
	} else {
		return 0;
	}
	return 1;
}

User avatar
Izhido
Posts: 107
Joined: Fri Oct 19, 2007 10:57 pm
Location: Costa Rica
Contact:

Re: Loading and Playing Wav, problem in Wii

Post by Izhido » Wed Sep 29, 2010 3:48 pm

Hola! Mira... me temo que, en realidad, no entendimos bien tu duda. Google Translate, con toda la buena intención que tuvieron de ofrecer un servicio de traducción decente, a veces no logra bien su cometido. Creo que necesitaremos que reformules la pregunta (en inglés, por favor - no habemos muchos aquí que hablen español) a ver si logramos entender que ocurre con tu código. De acuerdo?
-----------------------------------------------------
Hello! Look.. I'm afraid we actually didn't understand your question. With Google Translate, well, as much as they tried to offer a decent translation services, it sometimes doesn't make the cut. I think we need you to reformulate your question (English please - very few of us speak Spanish in here) so we can get an idea of what might be wrong with your code. Deal?

the_marioga
Posts: 7
Joined: Wed Sep 29, 2010 12:06 pm

Re: Loading and Playing Wav, problem in Wii

Post by the_marioga » Wed Sep 29, 2010 7:41 pm

I need to load and play .wav files, without SDL or SDL_mixer, i have compiled this sources(first post), but when i test in my wii, it returns me a Code Dump, These functions are bad? (first post) What should I do to load and play wav correctly?

Thanks

Eke
Posts: 64
Joined: Sat Mar 01, 2008 11:01 am

Re: Loading and Playing Wav, problem in Wii

Post by Eke » Thu Sep 30, 2010 9:56 am

You should first learn how pointer are working in C.

here, pFmt is NOT allocated, it will crash as soon as a function try to access the memory address returned by the pointer (NULL by default).

here is a more correct code:

Code: Select all

   PCMWAVFmt pFmt;
int wavPlay(const char* file) {
   void *buf = LoadPCMWav(file, &pFmt);
   if (buf) {
      ASND_SetVoice(ASND_GetFirstUnusedVoice(), VOICE_STEREO_16BIT, 8000,0, buf, sizeof(buf), 255, 255, NULL);
   } else {
      return 0;
   }
   return 1;
}
However, this is only if you can assume the WAV file you are trying to play is indeed always Stereo 16 bit @ 8kHZ.
It's safer to use the pFmt structure to get that parameters, it should have been filled by the LoadPCMWav function, providing this has been done correctly:

the_marioga
Posts: 7
Joined: Wed Sep 29, 2010 12:06 pm

Re: Loading and Playing Wav, problem in Wii

Post by the_marioga » Thu Sep 30, 2010 4:47 pm

I patched and works thaks a lot for help me

the_marioga
Posts: 7
Joined: Wed Sep 29, 2010 12:06 pm

Re: Loading and Playing Wav, problem in Wii

Post by the_marioga » Fri Oct 01, 2010 1:13 pm

Sorry, i try to play and not hear anything, LoadPCMWav return me a NULL in this part of the source:

Code: Select all

    u32 stFrame = (pFmt->start != PCMClock(-1)) ? PCMClock2Frame(pFmt->start, pFmt->sample_rate) : 0;
    u32 enFrame = (pFmt->end   != PCMClock(-1)) ? PCMClock2Frame(pFmt->end  , pFmt->sample_rate) : pFmt->sample_count;
    enFrame = MIN(enFrame, pFmt->sample_count);
    stFrame = MIN(stFrame, enFrame);
    u32 npad = enFrame - stFrame; 
    if ( npad <= 0 )
    {
        CloseFile(fd);
        return NULL; //This is the NULL
    }
npad value is 0

Eke
Posts: 64
Joined: Sat Mar 01, 2008 11:01 am

Re: Loading and Playing Wav, problem in Wii

Post by Eke » Sat Oct 02, 2010 6:04 pm

At a first glance, that seems normal, pFmt.start and pFmt.end are never initialized and they would hold zero by default, hence the result is 0.
You probably need to initialize these fields to -1 before calling LoadPCMWav, in order to get the whole sound length.

I'd advise you to first learn how to use the functions you are calling, seems like you copy-pasted some code from another application but without really understanding what it does and how it works.

the_marioga
Posts: 7
Joined: Wed Sep 29, 2010 12:06 pm

Re: Loading and Playing Wav, problem in Wii

Post by the_marioga » Mon Oct 18, 2010 9:51 pm

now i use

Code: Select all

int wavPlayer(const char* file) {	
	pFmt.start=-1;
	pFmt.end=-1;
   void *buf = LoadPCMWav(file, &pFmt);
   s32 voice = ASND_GetFirstUnusedVoice();
   if (buf) {
      if (ASND_SetVoice(voice, VOICE_STEREO_16BIT, pFmt.sample_rate,0, buf, pFmt.sample_channel * pFmt.sample_count * pFmt.sample_byte, 255, 255, NULL) == SND_OK) {
		ASND_PauseVoice(voice, 0);
	  } else {
		return 0;
	  }
   } else {
      return 0;
   }
   return 1;
}
but i not hear nothing, why?

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests