Many fixes
Now using dynamic allocation for file name. Sleep mode disabled to allow playing of music whilst lid is closed via headphones. Fixed an issue where the 3DS screens would not appear when coming back from sleep mode. Fixed an issue where music may immediately stop playing after trying to play it. Music can now be listened to when the 3DS has its lid closed. Fixed an issue whereby the number of sample in the buffer was miscalculated. Music can now be played by pressing the R button, even when the 3DS lid is closed. Selecting a file still has to be done with the d-pad. Tested working on new 3DS. Only the first 8MiB of a wav file is currently played. Signed-off-by: Mahyar Koshkouei <deltabeard@users.noreply.github.com>
This commit is contained in:
209
source/main.c
209
source/main.c
@@ -9,30 +9,42 @@
|
||||
|
||||
#include <3ds.h>
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#define BUFFER_SIZE 1 * 1024 * 1024
|
||||
#define BUFFER_SIZE 8 * 1024 * 1024
|
||||
#define AUDIO_FOLDER "sdmc:/MUSIC/"
|
||||
#define CHANNEL 8
|
||||
#define CHANNEL 0x08
|
||||
|
||||
int main()
|
||||
/* Adds extra debugging text */
|
||||
#define DEBUG 0
|
||||
|
||||
/* From: http://stackoverflow.com/a/1644898 */
|
||||
#define debug_print(fmt, ...) \
|
||||
do { if (DEBUG) fprintf(stderr, "%d:%s(): " fmt, __LINE__,\
|
||||
__func__, __VA_ARGS__); } while (0)
|
||||
|
||||
#define err_print(err) \
|
||||
do { fprintf(stderr, "Error %d:%s(): %s", __LINE__, __func__, \
|
||||
err); } while (0)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
PrintConsole topScreen;
|
||||
PrintConsole bottomScreen;
|
||||
u8 fileMax = 0;
|
||||
u8 fileNum = 1;
|
||||
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
|
||||
if(R_FAILED(ndspInit()))
|
||||
{
|
||||
printf("Error %d: Could not initialize ndsp.", __LINE__);
|
||||
goto out;
|
||||
}
|
||||
consoleInit(GFX_TOP, &topScreen);
|
||||
consoleInit(GFX_BOTTOM, &bottomScreen);
|
||||
consoleSelect(&topScreen);
|
||||
|
||||
puts("Scanning audio directory.");
|
||||
|
||||
@@ -46,26 +58,30 @@ int main()
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("Couldn't open the directory");
|
||||
err_print("Opening directory failed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(fileMax == 0)
|
||||
{
|
||||
puts("Error: No files in audio folder.");
|
||||
err_print("No files in audio folder.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
|
||||
ndspSetOutputCount(1);
|
||||
consoleSelect(&bottomScreen);
|
||||
aptSetSleepAllowed(false);
|
||||
|
||||
while(aptMainLoop())
|
||||
{
|
||||
u32 kDown;
|
||||
char file[128]; //TODO: Make this dynamic.
|
||||
char* file = NULL;
|
||||
|
||||
hidScanInput();
|
||||
|
||||
gfxSwapBuffers();
|
||||
gfxFlushBuffers();
|
||||
gspWaitForVBlank();
|
||||
|
||||
kDown = hidKeysDown();
|
||||
|
||||
if(kDown & KEY_START)
|
||||
@@ -83,11 +99,11 @@ int main()
|
||||
printf("\rSelected file %d ", fileNum);
|
||||
}
|
||||
|
||||
if(kDown & KEY_A)
|
||||
if(kDown & (KEY_A | KEY_R))
|
||||
{
|
||||
u8 audioFileNum = 0;
|
||||
|
||||
dp = opendir(AUDIO_FOLDER);
|
||||
|
||||
if (dp != NULL)
|
||||
{
|
||||
while((ep = readdir(dp)) != NULL)
|
||||
@@ -96,20 +112,29 @@ int main()
|
||||
if(audioFileNum == fileNum)
|
||||
break;
|
||||
}
|
||||
(void)closedir(dp);
|
||||
snprintf(file, sizeof(file), "%s%s", AUDIO_FOLDER, ep->d_name);
|
||||
}
|
||||
playWav(file);
|
||||
}
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
if(closedir(dp) != 0)
|
||||
err_print("Closing directory failed.");
|
||||
|
||||
if(asprintf(&file, "%s%s", AUDIO_FOLDER, ep->d_name) == -1)
|
||||
{
|
||||
err_print("Constructing file name failed.");
|
||||
file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(file == NULL)
|
||||
err_print("Opening file failed.");
|
||||
else
|
||||
playWav(file);
|
||||
|
||||
free(file);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
puts("Exiting...");
|
||||
|
||||
ndspExit();
|
||||
gfxExit();
|
||||
return 0;
|
||||
}
|
||||
@@ -127,33 +152,36 @@ int playWav(const char *wav)
|
||||
u32 sample;
|
||||
u8 format;
|
||||
u8 channels;
|
||||
u32 bitness;
|
||||
u8* buffer1;
|
||||
u8* buffer2;
|
||||
off_t bytesRead1;
|
||||
off_t bytesRead2;
|
||||
u8 bitness;
|
||||
u32 byterate; // TODO: Not used.
|
||||
u32 blockalign;
|
||||
u32* buffer1 = NULL;
|
||||
off_t size;
|
||||
ndspWaveBuf waveBuf;
|
||||
off_t buffer_size;
|
||||
ndspWaveBuf waveBuf[2];
|
||||
|
||||
if(file == NULL)
|
||||
if(R_FAILED(ndspInit()))
|
||||
{
|
||||
puts("Opening file failed.");
|
||||
return 1;
|
||||
err_print("Initialising ndsp failed.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
if(size > BUFFER_SIZE)
|
||||
size = BUFFER_SIZE;
|
||||
buffer_size = BUFFER_SIZE;
|
||||
else
|
||||
buffer_size = size;
|
||||
|
||||
buffer1 = linearAlloc(size);
|
||||
buffer2 = linearAlloc(size);
|
||||
buffer1 = (u32*) linearAlloc(buffer_size);
|
||||
|
||||
if(fread(header, 1, 44, file) == 0)
|
||||
{
|
||||
puts("Unable to read WAV file.");
|
||||
err_print("Unable to read WAV file.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -173,9 +201,13 @@ int playWav(const char *wav)
|
||||
channels = (header[23]<<8) + (header[22]);
|
||||
sample = (header[27]<<24) + (header[26]<<16) + (header[25]<<8) +
|
||||
(header[24]);
|
||||
byterate = (header[31]<<24) + (header[30]<<16) + (header[29]<<8) +
|
||||
(header[28]);
|
||||
blockalign = (header[33]<<8) + (header[32]);
|
||||
bitness = (header[35]<<8) + (header[34]);
|
||||
printf("Format: %s(%d), Ch: %d, Sam: %lu, bit: %lu\n",
|
||||
format == 1 ? "PCM" : "Other", format, channels, sample, bitness);
|
||||
printf("Format: %s(%d), Ch: %d, Sam: %lu, bit: %d, BR: %lu, BA: %lu\n",
|
||||
format == 1 ? "PCM" : "Other", format, channels, sample, bitness,
|
||||
byterate, blockalign);
|
||||
|
||||
if(channels > 2)
|
||||
{
|
||||
@@ -199,81 +231,66 @@ int playWav(const char *wav)
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Bitness of %lu unsupported.\n", bitness);
|
||||
printf("Bitness of %d unsupported.\n", bitness);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fread(buffer1, 1, buffer_size, file);
|
||||
ndspChnReset(CHANNEL);
|
||||
ndspChnWaveBufClear(CHANNEL);
|
||||
ndspChnSetInterp(CHANNEL, NDSP_INTERP_NONE);
|
||||
ndspChnSetRate(CHANNEL, sample);
|
||||
ndspChnSetFormat(CHANNEL, bitness);
|
||||
memset(&waveBuf, 0, sizeof(ndspWaveBuf));
|
||||
waveBuf.data_vaddr = buffer1;
|
||||
waveBuf.status = NDSP_WBUF_FREE;
|
||||
|
||||
memset(waveBuf, 0, sizeof(waveBuf));
|
||||
waveBuf[0].nsamples = buffer_size / blockalign;
|
||||
waveBuf[0].data_vaddr = &buffer1[0];
|
||||
//waveBuf[1].nsamples = buffer_size / bitness / 2;
|
||||
//waveBuf[1].data_vaddr = &buffer1[buffer_size / 2];
|
||||
ndspChnWaveBufAdd(CHANNEL, &waveBuf[0]);
|
||||
//ndspChnWaveBufAdd(CHANNEL, &waveBuf[1]);
|
||||
DSP_FlushDataCache(buffer1, buffer_size);
|
||||
|
||||
printf("Playing %s\n", wav);
|
||||
|
||||
while((bytesRead1 = fread(buffer1, 1, size, file)) > 0)
|
||||
/**
|
||||
* There may be a chance that the music has not started by the time we get
|
||||
* to the while loop. So we ensure that music has started here.
|
||||
*/
|
||||
while(ndspChnIsPlaying(CHANNEL) == false)
|
||||
{}
|
||||
|
||||
while(ndspChnIsPlaying(CHANNEL) == true)
|
||||
{
|
||||
u8 status = 1;
|
||||
u32 kDown;
|
||||
|
||||
if(R_FAILED(GSPGPU_FlushDataCache(buffer1, size)))
|
||||
puts("Flush failed.");
|
||||
gfxSwapBuffers();
|
||||
gfxFlushBuffers();
|
||||
gspWaitForVBlank();
|
||||
|
||||
while(ndspChnIsPlaying(8))
|
||||
hidScanInput();
|
||||
kDown = hidKeysDown();
|
||||
|
||||
if(kDown & KEY_B)
|
||||
break;
|
||||
|
||||
if(kDown & KEY_X)
|
||||
{
|
||||
u32 kDown;
|
||||
|
||||
hidScanInput();
|
||||
kDown = hidKeysDown();
|
||||
|
||||
if(kDown & KEY_B)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ndspChnWaveBufAdd(CHANNEL, &waveBuf);
|
||||
|
||||
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;
|
||||
|
||||
if(csndPlaySound(8, bitness | SOUND_ONE_SHOT, sample * channels, 1, 0,
|
||||
buffer2, NULL, bytesRead2) != 0)
|
||||
{
|
||||
printf("Error %d.\n", __LINE__);
|
||||
goto out;
|
||||
debug_print("Pos: %lx of %lx\n", ndspChnGetSamplePos(CHANNEL),
|
||||
buffer_size / bitness);
|
||||
}
|
||||
}
|
||||
|
||||
debug_print("Pos: %lx\n", ndspChnGetSamplePos(CHANNEL));
|
||||
debug_print("%s\n", "Before clear");
|
||||
|
||||
ndspChnWaveBufClear(CHANNEL);
|
||||
|
||||
out:
|
||||
puts("Stopping playback.");
|
||||
|
||||
csndExecCmds(true);
|
||||
CSND_SetPlayState(8, 0);
|
||||
if(R_FAILED(CSND_UpdateInfo(0)))
|
||||
printf("Failed to stop audio playback.\n");
|
||||
|
||||
ndspExit();
|
||||
fclose(file);
|
||||
linearFree(buffer1);
|
||||
linearFree(buffer2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user