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:
144
source/main.c
144
source/main.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user