Player fixes and file selector

Fixed an issue where the first part of a WAV file would not be played.
Fixed an issue where a random part of the WAV file would play after the
file had finished playing.
Fixed an issue where the audio file was not closed after it had finished
playing.
Fixed an issue whereby the current file would continue playing after
returning to the main menu.

Added basic file selector to select different WAV audio files in the
/audio/ folder.
Now using two buffers to play audio. Whilst one buffer is playing, the
other buffer is played. Buffer size set to a magic value of 1MiB.

Tested on New 3DS. Currently working with 48000Hz, 16 Bit WAV files.

TODO (in order):
Refactor duplicate code.
Automatically detect WAV sampling rate, resolution, etc.
Remove debug messages.
Add file browser.

Signed-off-by: Mahyar Koshkouei <deltabeard@users.noreply.github.com>
This commit is contained in:
Mahyar Koshkouei
2016-10-25 23:30:50 +01:00
parent 69cd402df1
commit b60cec86b9

View File

@@ -8,14 +8,22 @@
*/
#include <3ds.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 1131072
#define BUFFER_SIZE 1 * 1024 * 1024
#define AUDIO_FOLDER "sdmc:/audio/"
int playWav(const char *wav);
int main()
{
DIR *dp;
struct dirent *ep;
u8 fileMax = 0;
u8 fileNum = 0;
gfxInitDefault();
consoleInit(GFX_BOTTOM, NULL);
@@ -29,20 +37,28 @@ int main()
else
puts("CSND initialized.");
/**
* Open File
* Read 16 kb from file
* Play 16 kb buffer
* Wait until finished playing
* Read next 16 kb in the meantime
* Play next chunk
* Continue until end of file
*/
dp = opendir("sdmc:/audio/");
if (dp != NULL)
{
while(ep = readdir(dp))
printf("%d: %s\n", ++fileMax, ep->d_name);
(void)closedir(dp);
}
else
puts("Couldn't open the directory");
if(fileMax == 0)
{
puts("Error: No files in audio folder.");
goto out;
}
while(aptMainLoop())
{
u32 kDown;
u8 ret;
char file[128]; //TODO: Make this dynamic.
hidScanInput();
gspWaitForVBlank();
@@ -51,7 +67,39 @@ int main()
if(kDown & KEY_START)
break;
if(kDown & KEY_A && (ret = playWav("sdmc:/audio/audio3.wav") != 0))
if(kDown & KEY_UP && fileNum < fileMax)
{
fileNum++;
printf("Selected file %d\n", fileNum);
}
if(kDown & KEY_DOWN && fileNum > 1)
{
fileNum--;
printf("Selected file %d\n", fileNum);
}
if(kDown & KEY_X)
{
u8 audioFileNum = 0;
dp = opendir(AUDIO_FOLDER);
if (dp != NULL)
{
while(ep = readdir(dp))
{
audioFileNum++;
if(audioFileNum == fileNum)
break;
}
(void)closedir(dp);
snprintf(file, sizeof(file), "%s%s", AUDIO_FOLDER, ep->d_name);
}
printf("Opening file %s\n", file);
playWav(file); // No error checking. Terribad.
}
if(kDown & KEY_A && (ret = playWav("sdmc:/audio/audio.wav") != 0))
{
printf("Error ");
switch(ret)
@@ -91,9 +139,12 @@ out:
int playWav(const char *wav)
{
FILE *file = fopen(wav, "rb");
u8* buffer;
off_t bytesRead;
u8* buffer1;
u8* buffer2;
off_t bytesRead1;
off_t bytesRead2;
off_t size;
u8 chunk = 0;
printf("Got to line %d\n", __LINE__);
@@ -109,26 +160,83 @@ int playWav(const char *wav)
size = BUFFER_SIZE;
printf("Got to line %d\n", __LINE__);
buffer = linearAlloc(size);
buffer1 = linearAlloc(size);
buffer2 = linearAlloc(size);
printf("Got to line %d. Size: %d\n", __LINE__, size);
while((bytesRead = fread(buffer, 1, size, file)) > 0)
while((bytesRead1 = fread(buffer1, 1, size, file)) > 0)
{
u8 status = 1;
printf("Chunk %d", ++chunk);
while(status != 0)
{
u32 kDown;
csndIsPlaying(8, &status);
printf("Got to line %d. Read %d bytes\n", __LINE__, bytesRead);
hidScanInput();
kDown = hidKeysDown();
if(kDown & KEY_B)
goto out;
}
if(R_FAILED(GSPGPU_FlushDataCache(buffer1, size)))
puts("Flush failed.");
if(csndPlaySound(8, SOUND_FORMAT_16BIT | SOUND_ONE_SHOT, 48000, 1, 0,
buffer, buffer, size) != 0)
buffer1, NULL, bytesRead1) != 0)
{
printf("Error %d.\n", __LINE__);
goto out;
}
bytesRead2 = fread(buffer2, 1, size, file);
if(R_FAILED(GSPGPU_FlushDataCache(buffer2, size)))
puts("Flush failed.");
status = 1;
while(status != 0)
{
u32 kDown;
csndIsPlaying(8, &status);
hidScanInput();
kDown = hidKeysDown();
if(kDown & KEY_B)
goto out;
}
if(bytesRead2 == 0)
goto out;
printf("Chunk %d", ++chunk);
if(csndPlaySound(8, SOUND_FORMAT_16BIT | SOUND_ONE_SHOT, 48000, 1, 0,
buffer2, NULL, bytesRead2) != 0)
{
printf("Error %d.\n", __LINE__);
goto out;
}
}
out:
printf("Got to line %d\n", __LINE__);
linearFree(buffer);
csndExecCmds(true);
CSND_SetPlayState(8, 0);
if(R_FAILED(CSND_UpdateInfo(0)))
printf("Failed to stop audio playback.\n");
fclose(file);
linearFree(buffer1);
linearFree(buffer2);
return 0;
}