Merge pull request #6393 from hrydgard/menu-audio

Play the game's SND0.AT3 when a game is selected in the menu and on the "game screen".
This commit is contained in:
Henrik Rydgård 2014-06-22 19:35:16 +02:00
commit b2ae317560
19 changed files with 350 additions and 75 deletions

View File

@ -1401,6 +1401,7 @@ endif()
set(NativeAppSource
UI/NativeApp.cpp
UI/BackgroundAudio.cpp
UI/DevScreens.cpp
UI/EmuScreen.cpp
android/jni/TestRunner.cpp

View File

@ -18,6 +18,7 @@
#pragma once
// Extremely simple serialization framework.
// Currently mis-named, a native ChunkFile is something different (a RIFF file)
// (mis)-features:
// + Super fast

View File

@ -81,7 +81,8 @@ int sceAudiocodecInit(u32 ctxPtr, int codec) {
if (removeDecoder(ctxPtr)) {
WARN_LOG_REPORT(HLE, "sceAudiocodecInit(%08x, %d): replacing existing context", ctxPtr, codec);
}
auto decoder = new SimpleAudio(ctxPtr, codec);
auto decoder = new SimpleAudio(codec);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
INFO_LOG(ME, "sceAudiocodecInit(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
DEBUG_LOG(ME, "Number of playing sceAudioCodec audios : %d", (int)audioList.size());
@ -107,7 +108,8 @@ int sceAudiocodecDecode(u32 ctxPtr, int codec) {
if (!decoder && oldStateLoaded) {
// We must have loaded an old state that did not have sceAudiocodec information.
// Fake it by creating the desired context.
decoder = new SimpleAudio(ctxPtr, codec);
decoder = new SimpleAudio(codec);
decoder->SetCtxPtr(ctxPtr);
audioList[ctxPtr] = decoder;
}
@ -181,7 +183,8 @@ void __sceAudiocodecDoState(PointerWrap &p){
p.DoArray(codec_, s >= 2 ? count : (int)ARRAY_SIZE(codec_));
p.DoArray(ctxPtr_, s >= 2 ? count : (int)ARRAY_SIZE(ctxPtr_));
for (int i = 0; i < count; i++) {
auto decoder = new SimpleAudio(ctxPtr_[i], codec_[i]);
auto decoder = new SimpleAudio(codec_[i]);
decoder->SetCtxPtr(ctxPtr_[i]);
audioList[ctxPtr_[i]] = decoder;
}
delete[] codec_;

View File

@ -333,7 +333,7 @@ int sceMp3Init(u32 mp3) {
// for mp3, if required freq is 48000, reset resampling Frequency to 48000 seems get better sound quality (e.g. Miku Custom BGM)
if (ctx->freq == 48000) {
ctx->decoder->setResampleFrequency(ctx->freq);
ctx->decoder->SetResampleFrequency(ctx->freq);
}
// For mp3 file, if ID3 tag is detected, we must move startPos to 0x400 (stream start position), remove 0x400 bytes of the sourcebuff, and reduce the available buffer size by 0x400
@ -557,7 +557,7 @@ u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumedAddr, u
int outpcmbytes = 0;
ctx->decoder->Decode((void*)inbuff, 4096, outbuff, &outpcmbytes);
Memory::Write_U32(ctx->decoder->getSourcePos(), sourceBytesConsumedAddr);
Memory::Write_U32(ctx->decoder->GetSourcePos(), sourceBytesConsumedAddr);
Memory::Write_U32(outpcmbytes, sampleBytesAddr);
return 0;
}

View File

@ -60,14 +60,8 @@ bool SimpleAudio::GetAudioCodecID(int audioType) {
#endif // USE_FFMPEG
}
SimpleAudio::SimpleAudio(int audioType)
: codec_(0), codecCtx_(0), swrCtx_(0), audioType(audioType), outSamples(0), wanted_resample_freq(44100) {
Init();
}
SimpleAudio::SimpleAudio(u32 ctxPtr, int audioType)
: codec_(0), codecCtx_(0), swrCtx_(0), ctxPtr(ctxPtr), audioType(audioType), outSamples(0), wanted_resample_freq(44100) {
SimpleAudio::SimpleAudio(int audioType, int sample_rate, int channels)
: ctxPtr(0xFFFFFFFF), audioType(audioType), sample_rate_(sample_rate), channels_(channels), codec_(0), codecCtx_(0), swrCtx_(0), outSamples(0), srcPos(0), wanted_resample_freq(44100), extradata_(0) {
Init();
}
@ -97,19 +91,24 @@ void SimpleAudio::Init() {
ERROR_LOG(ME, "Failed to allocate a codec context");
return;
}
codecCtx_->channels = 2;
codecCtx_->channel_layout = AV_CH_LAYOUT_STEREO;
codecCtx_->sample_rate = 44100;
// Open codec
codecCtx_->channels = channels_;
codecCtx_->channel_layout = channels_ == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
codecCtx_->sample_rate = sample_rate_;
OpenCodec();
#endif // USE_FFMPEG
}
bool SimpleAudio::OpenCodec() {
#ifdef USE_FFMPEG
AVDictionary *opts = 0;
bool result = true;
if (avcodec_open2(codecCtx_, codec_, &opts) < 0) {
ERROR_LOG(ME, "Failed to open codec");
av_dict_free(&opts);
return;
result = false;
}
av_dict_free(&opts);
#endif // USE_FFMPEG
return result;
}
bool SimpleAudio::ResetCodecCtx(int channels, int samplerate){
@ -128,21 +127,35 @@ bool SimpleAudio::ResetCodecCtx(int channels, int samplerate){
codecCtx_->channels = channels;
codecCtx_->channel_layout = channels==2?AV_CH_LAYOUT_STEREO:AV_CH_LAYOUT_MONO;
codecCtx_->sample_rate = samplerate;
// Open codec
AVDictionary *opts = 0;
if (avcodec_open2(codecCtx_, codec_, &opts) < 0) {
ERROR_LOG(ME, "Failed to open codec");
av_dict_free(&opts);
return false;
}
av_dict_free(&opts);
OpenCodec();
return true;
#endif
return false;
}
void SimpleAudio::SetExtraData(u8 *data, int size, int wav_bytes_per_packet) {
delete [] extradata_;
extradata_ = 0;
if (data != 0) {
extradata_ = new u8[size];
memcpy(extradata_, data, size);
}
#ifdef USE_FFMPEG
if (codecCtx_) {
codecCtx_->extradata = extradata_;
codecCtx_->extradata_size = size;
codecCtx_->block_align = wav_bytes_per_packet;
OpenCodec();
}
#endif
}
SimpleAudio::~SimpleAudio() {
#ifdef USE_FFMPEG
if (swrCtx_)
swr_free(&swrCtx_);
if (frame_)
av_frame_free(&frame_);
if (codecCtx_)
@ -151,6 +164,8 @@ SimpleAudio::~SimpleAudio() {
codecCtx_ = 0;
codec_ = 0;
#endif // USE_FFMPEG
delete [] extradata_;
extradata_ = 0;
}
bool SimpleAudio::IsOK() const {
@ -183,7 +198,7 @@ bool SimpleAudio::Decode(void* inbuf, int inbytes, uint8_t *outbuf, int *outbyte
srcPos = 0;
int len = avcodec_decode_audio4(codecCtx_, frame_, &got_frame, &packet);
if (len < 0) {
ERROR_LOG(ME, "Error decoding Audio frame");
ERROR_LOG(ME, "Error decoding Audio frame (%i bytes): %i (%08x)", inbytes, len, len);
// TODO: cleanup
return false;
}
@ -197,30 +212,32 @@ bool SimpleAudio::Decode(void* inbuf, int inbytes, uint8_t *outbuf, int *outbyte
int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO; // we want stereo output layout
int64_t dec_channel_layout = frame_->channel_layout; // decoded channel layout
swrCtx_ = swr_alloc_set_opts(
swrCtx_,
wanted_channel_layout,
AV_SAMPLE_FMT_S16,
wanted_resample_freq,
dec_channel_layout,
codecCtx_->sample_fmt,
codecCtx_->sample_rate,
0,
NULL);
if (!swrCtx_) {
swrCtx_ = swr_alloc_set_opts(
swrCtx_,
wanted_channel_layout,
AV_SAMPLE_FMT_S16,
wanted_resample_freq,
dec_channel_layout,
codecCtx_->sample_fmt,
codecCtx_->sample_rate,
0,
NULL);
if (!swrCtx_ || swr_init(swrCtx_) < 0) {
ERROR_LOG(ME, "swr_init: Failed to initialize the resampling context");
avcodec_close(codecCtx_);
codec_ = 0;
return false;
if (!swrCtx_ || swr_init(swrCtx_) < 0) {
ERROR_LOG(ME, "swr_init: Failed to initialize the resampling context");
avcodec_close(codecCtx_);
codec_ = 0;
return false;
}
}
// convert audio to AV_SAMPLE_FMT_S16
int swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const u8 **)frame_->extended_data, frame_->nb_samples);
if (swrRet < 0) {
ERROR_LOG(ME, "swr_convert: Error while converting %d", swrRet);
return false;
}
swr_free(&swrCtx_);
// output samples per frame, we should *2 since we have two channels
outSamples = swrRet * 2;
@ -240,18 +257,14 @@ bool SimpleAudio::Decode(void* inbuf, int inbytes, uint8_t *outbuf, int *outbyte
#endif // USE_FFMPEG
}
int SimpleAudio::getOutSamples(){
int SimpleAudio::GetOutSamples(){
return outSamples;
}
int SimpleAudio::getSourcePos(){
int SimpleAudio::GetSourcePos(){
return srcPos;
}
void SimpleAudio::setResampleFrequency(int freq){
wanted_resample_freq = freq;
}
void AudioClose(SimpleAudio **ctx) {
#ifdef USE_FFMPEG
delete *ctx;
@ -349,9 +362,9 @@ u32 AuCtx::AuDecode(u32 pcmAddr)
// count total output pcm size
outpcmbufsize += pcmframesize;
// count total output samples
SumDecodedSamples += decoder->getOutSamples();
SumDecodedSamples += decoder->GetOutSamples();
// get consumed source length
int srcPos = decoder->getSourcePos();
int srcPos = decoder->GetSourcePos();
// remove the consumed source
sourcebuff.erase(0, srcPos);
// reduce the available Aubuff size

View File

@ -33,11 +33,6 @@ struct SwrContext;
// Based on http://ffmpeg.org/doxygen/trunk/doc_2examples_2decoding_encoding_8c-example.html#_a13
// Ideally, Maxim's Atrac3+ decoder would be available as a standalone library
// that we could link, as that would be totally sufficient for the use case here.
// However, it will be maintained as a part of FFMPEG so that's the way we'll go
// for simplicity and sanity.
// audioType
enum {
PSP_CODEC_AT3PLUS = 0x00001000,
@ -48,38 +43,48 @@ enum {
class SimpleAudio {
public:
SimpleAudio(int audioType);
SimpleAudio(u32 ctxPtr, int audioType);
SimpleAudio(int audioType, int sample_rate = 44100, int channels = 2);
~SimpleAudio();
bool Decode(void* inbuf, int inbytes, uint8_t *outbuf, int *outbytes);
bool IsOK() const;
int getOutSamples();
int getSourcePos();
int GetOutSamples();
int GetSourcePos();
bool ResetCodecCtx(int channels, int samplerate);
void setResampleFrequency(int freq);
bool GetAudioCodecID(int audioType); // Get audioCodecId from audioType
// Not save stated, only used by UI. Used for ATRAC3 (non+) files.
void SetExtraData(u8 *data, int size, int wav_bytes_per_packet);
// These two are only here because of save states.
int GetAudioType() const { return audioType; }
void SetResampleFrequency(int freq) { wanted_resample_freq = freq; }
// Just metadata.
void SetCtxPtr(u32 ptr) { ctxPtr = ptr; }
u32 GetCtxPtr() const { return ctxPtr; }
private:
void Init();
bool OpenCodec();
u32 ctxPtr;
int audioType;
int sample_rate_;
int channels_;
int outSamples; // output samples per frame
int srcPos; // bytes consumed in source during the last decoding
int wanted_resample_freq; // wanted resampling rate/frequency
#ifdef USE_FFMPEG
AVFrame *frame_;
AVCodec *codec_;
AVCodecContext *codecCtx_;
SwrContext *swrCtx_;
int audioCodecId; // AV_CODEC_ID_XXX
#endif // USE_FFMPEG
// Not savestated, only used by UI.
u8 *extradata_;
};
void AudioClose(SimpleAudio **ctx);

View File

@ -91,6 +91,7 @@ symbian {
# UI
SOURCES += $$P/UI/*Screen.cpp \
$$P/UI/*Screens.cpp \
$$P/UI/BackgroundAudio.cpp \
$$P/UI/Store.cpp \
$$P/UI/GamepadEmu.cpp \
$$P/UI/GameInfoCache.cpp \

208
UI/BackgroundAudio.cpp Normal file
View File

@ -0,0 +1,208 @@
#include <string>
#include "base/logging.h"
#include "base/timeutil.h"
#include "base/mutex.h"
#include "native/file/chunk_file.h"
#include "Common/CommonTypes.h"
#include "Core/HW/SimpleAudioDec.h"
#include "Common/FixedSizeQueue.h"
#include "GameInfoCache.h"
// Really simple looping in-memory AT3 player that also takes care of reading the file format.
// Turns out that AT3 files used for this are modified WAVE files so fairly easy to parse.
class AT3PlusReader {
public:
AT3PlusReader(const std::string &data)
: data_(data),
raw_offset_(0),
file_((const uint8_t *)&data[0],
(int32_t)data.size()),
raw_data_(0),
raw_data_size_(0),
buffer_(0),
decoder_(0) {
// Normally 8k but let's be safe.
buffer_ = new short[32 * 1024];
int codec = PSP_CODEC_AT3PLUS;
u8 at3_extradata[16];
int num_channels, sample_rate, numFrames, samplesPerSec, avgBytesPerSec, Nothing;
if (file_.descend('RIFF')) {
file_.readInt(); //get past 'WAVE'
if (file_.descend('fmt ')) { //enter the format chunk
int temp = file_.readInt();
int format = temp & 0xFFFF;
switch (format) {
case 0xFFFE:
codec = PSP_CODEC_AT3PLUS;
break;
case 0x270:
codec = PSP_CODEC_AT3;
break;
default:
ERROR_LOG(HLE, "Unexpected SND0.AT3 format %04x", format);
return;
}
num_channels = temp >> 16;
samplesPerSec = file_.readInt();
avgBytesPerSec = file_.readInt();
temp = file_.readInt();
raw_bytes_per_frame_ = temp & 0xFFFF;
Nothing = temp >> 16;
if (codec == PSP_CODEC_AT3) {
// The first two bytes are actually not useful part of the extradata.
// We already read 16 bytes, so make sure there's enough left.
if (file_.getCurrentChunkSize() >= 32) {
file_.readData(at3_extradata, 16);
} else {
memset(at3_extradata, 0, sizeof(at3_extradata));
}
}
file_.ascend();
// ILOG("got fmt data: %i", samplesPerSec);
} else {
ELOG("Error - no format chunk in wav");
file_.ascend();
return;
}
if (file_.descend('data')) { //enter the data chunk
int numBytes = file_.getCurrentChunkSize();
numFrames = numBytes / raw_bytes_per_frame_; // numFrames
raw_data_ = (uint8_t *)malloc(numBytes);
raw_data_size_ = numBytes;
if (/*raw_bytes_per_frame_ == 280 && */ num_channels == 2) {
file_.readData(raw_data_, numBytes);
} else {
ELOG("Error - bad blockalign or channels");
free(raw_data_);
raw_data_ = 0;
return;
}
file_.ascend();
} else {
ELOG("Error - no data chunk in wav");
file_.ascend();
return;
}
file_.ascend();
} else {
ELOG("Could not descend into RIFF file");
return;
}
sample_rate = samplesPerSec;
decoder_ = new SimpleAudio(codec, sample_rate, num_channels);
if (codec == PSP_CODEC_AT3) {
decoder_->SetExtraData(&at3_extradata[2], 14, raw_bytes_per_frame_);
}
ILOG("read ATRAC, frames: %i, rate %i", numFrames, sample_rate);
}
~AT3PlusReader() {
}
void Shutdown() {
free(raw_data_);
raw_data_ = 0;
delete[] buffer_;
buffer_ = 0;
delete decoder_;
decoder_ = 0;
}
bool IsOK() { return raw_data_ != 0; }
bool Read(short *buffer, int len) {
if (!raw_data_)
return false;
while (bgQueue.size() < len * 2) {
int outBytes;
decoder_->Decode(raw_data_ + raw_offset_, raw_bytes_per_frame_, (uint8_t *)buffer_, &outBytes);
if (!outBytes)
return false;
for (int i = 0; i < outBytes / 2; i++) {
bgQueue.push(buffer_[i]);
}
// loop!
raw_offset_ += raw_bytes_per_frame_;
if (raw_offset_ >= raw_data_size_) {
raw_offset_ = 0;
}
}
for (int i = 0; i < len * 2; i++) {
buffer[i] = bgQueue.pop_front();
}
return true;
}
private:
const std::string &data_;
ChunkFile file_;
uint8_t *raw_data_;
int raw_data_size_;
int raw_offset_;
int raw_bytes_per_frame_;
FixedSizeQueue<s16, 128 * 1024> bgQueue;
short *buffer_;
SimpleAudio *decoder_;
};
static recursive_mutex bgMutex;
static std::string bgGamePath;
static int playbackOffset;
static AT3PlusReader *at3Reader;
static double gameLastChanged;
void SetBackgroundAudioGame(const std::string &path) {
time_update();
lock_guard lock(bgMutex);
if (path == bgGamePath) {
// Do nothing
return;
}
gameLastChanged = time_now_d();
if (at3Reader) {
at3Reader->Shutdown();
delete at3Reader;
at3Reader = 0;
}
playbackOffset = 0;
bgGamePath = path;
}
int MixBackgroundAudio(short *buffer, int size) {
time_update();
lock_guard lock(bgMutex);
// If there's a game, and some time has passed since the selected game
// last changed... (to prevent crazy amount of reads when skipping through a list)
if (!at3Reader && bgGamePath.size() && (time_now_d() - gameLastChanged > 0.5)) {
// Grab some audio from the current game and play it.
GameInfo *gameInfo = g_gameInfoCache.GetInfo(bgGamePath, GAMEINFO_WANTSND);
if (!gameInfo)
return 0;
if (gameInfo->sndFileData.size()) {
const std::string &data = gameInfo->sndFileData;
at3Reader = new AT3PlusReader(data);
}
}
if (!at3Reader || !at3Reader->Read(buffer, size)) {
memset(buffer, 0, size * 2 * sizeof(s16));
}
return 0;
}

6
UI/BackgroundAudio.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <string>
void SetBackgroundAudioGame(const std::string &path);
int MixBackgroundAudio(short *buffer, int size);

View File

@ -576,12 +576,15 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, int wantFlags) {
}
if (info->iconDataLoaded) {
SetupTexture(info, info->iconTextureData, info->iconTexture, info->timeIconWasLoaded);
info->iconDataLoaded = false;
}
if (info->pic0DataLoaded) {
SetupTexture(info, info->pic0TextureData, info->pic0Texture, info->timePic0WasLoaded);
info->pic0DataLoaded = false;
}
if (info->pic1DataLoaded) {
SetupTexture(info, info->pic1TextureData, info->pic1Texture, info->timePic1WasLoaded);
info->pic1DataLoaded = false;
}
iter->second->lastAccessedTime = time_now_d();
return iter->second;

View File

@ -31,9 +31,19 @@
#include "UI/GameInfoCache.h"
#include "UI/MiscScreens.h"
#include "UI/MainScreen.h"
#include "UI/BackgroundAudio.h"
#include "Core/Host.h"
#include "Core/Config.h"
GameScreen::GameScreen(const std::string &gamePath) : UIDialogScreenWithGameBackground(gamePath) {
SetBackgroundAudioGame(gamePath);
}
GameScreen::~GameScreen() {
SetBackgroundAudioGame("");
}
void GameScreen::CreateViews() {
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);

View File

@ -29,7 +29,8 @@
class GameScreen : public UIDialogScreenWithGameBackground {
public:
GameScreen(const std::string &gamePath) : UIDialogScreenWithGameBackground(gamePath) {}
GameScreen(const std::string &gamePath);
~GameScreen();
virtual void update(InputState &input);

View File

@ -35,6 +35,7 @@
#include "Core/Reporting.h"
#include "Core/SaveState.h"
#include "UI/BackgroundAudio.h"
#include "UI/EmuScreen.h"
#include "UI/MainScreen.h"
#include "UI/GameScreen.h"
@ -235,7 +236,8 @@ void GameButton::Draw(UIContext &dc) {
if (HasFocus()) {
dc.Draw()->Flush();
dc.RebindTexture();
dc.Draw()->DrawImage4Grid(dc.theme->dropShadow4Grid, x - dropsize*1.5f, y - dropsize*1.5f, x+w + dropsize*1.5f, y+h+dropsize*1.5f, alphaMul(color, 1.0f), 1.0f);
float pulse = sinf(time_now() * 7.0f) * 0.25 + 0.8;
dc.Draw()->DrawImage4Grid(dc.theme->dropShadow4Grid, x - dropsize*1.5f, y - dropsize*1.5f, x + w + dropsize*1.5f, y + h + dropsize*1.5f, alphaMul(color, pulse), 1.0f);
dc.Draw()->Flush();
} else {
dc.Draw()->Flush();
@ -702,10 +704,16 @@ UI::EventReturn GameBrowser::NavigateClick(UI::EventParams &e) {
return UI::EVENT_DONE;
}
MainScreen::MainScreen() : highlightProgress_(0.0f), prevHighlightProgress_(0.0f), backFromStore_(false) {
MainScreen::MainScreen() : highlightProgress_(0.0f), prevHighlightProgress_(0.0f), backFromStore_(false), lockBackgroundAudio_(false) {
System_SendMessage("event", "mainscreen");
SetBackgroundAudioGame("");
}
MainScreen::~MainScreen() {
SetBackgroundAudioGame("");
}
void MainScreen::CreateViews() {
// Information in the top left.
// Back button to the bottom left.
@ -878,6 +886,7 @@ void MainScreen::sendMessage(const char *message, const char *value) {
if (!strcmp(message, "boot")) {
screenManager()->switchScreen(new EmuScreen(value));
SetBackgroundAudioGame(value);
}
if (!strcmp(message, "control mapping")) {
UpdateUIState(UISTATE_MENU);
@ -963,17 +972,19 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, f
}
UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) {
#ifdef _WIN32
#ifdef _WIN32
std::string path = ReplaceAll(e.s, "\\", "/");
#else
std::string path = e.s;
#endif
SetBackgroundAudioGame(path);
lockBackgroundAudio_ = true;
screenManager()->push(new GameScreen(path));
return UI::EVENT_DONE;
}
UI::EventReturn MainScreen::OnGameHighlight(UI::EventParams &e) {
#ifdef _WIN32
#ifdef _WIN32
std::string path = ReplaceAll(e.s, "\\", "/");
#else
std::string path = e.s;
@ -990,11 +1001,15 @@ UI::EventReturn MainScreen::OnGameHighlight(UI::EventParams &e) {
highlightedGamePath_ = path;
highlightProgress_ = 0.0f;
}
if ((!highlightedGamePath_.empty() || e.a == FF_LOSTFOCUS) && !lockBackgroundAudio_)
SetBackgroundAudioGame(highlightedGamePath_);
lockBackgroundAudio_ = false;
return UI::EVENT_DONE;
}
UI::EventReturn MainScreen::OnGameSelectedInstant(UI::EventParams &e) {
#ifdef _WIN32
#ifdef _WIN32
std::string path = ReplaceAll(e.s, "\\", "/");
#else
std::string path = e.s;

View File

@ -29,6 +29,7 @@
class MainScreen : public UIScreenWithBackground {
public:
MainScreen();
~MainScreen();
virtual bool isTopLevel() const { return true; }
@ -68,6 +69,7 @@ private:
std::string prevHighlightedGamePath_;
float highlightProgress_;
float prevHighlightProgress_;
bool lockBackgroundAudio_;
bool backFromStore_;
};

View File

@ -86,6 +86,7 @@
#include "UI/OnScreenDisplay.h"
#include "UI/MiscScreens.h"
#include "UI/TiltEventProcessor.h"
#include "UI/BackgroundAudio.h"
#if !defined(MOBILE_DEVICE)
#include "Common/KeyMap.h"
@ -207,8 +208,8 @@ int NativeMix(short *audio, int num_samples) {
if (g_mixer && GetUIState() == UISTATE_INGAME) {
num_samples = g_mixer->Mix(audio, num_samples);
} else {
// MixBackgroundAudio(audio, num_samples);
memset(audio, 0, num_samples * 2 * sizeof(short));
MixBackgroundAudio(audio, num_samples);
// memset(audio, 0, num_samples * 2 * sizeof(short));
}
#ifdef _WIN32

View File

@ -19,6 +19,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BackgroundAudio.cpp" />
<ClCompile Include="ControlMappingScreen.cpp" />
<ClCompile Include="CwCheatScreen.cpp" />
<ClCompile Include="DevScreens.cpp" />
@ -41,6 +42,7 @@
<ClCompile Include="ui_atlas.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="BackgroundAudio.h" />
<ClInclude Include="ControlMappingScreen.h" />
<ClInclude Include="DevScreens.h" />
<ClInclude Include="EmuScreen.h" />

View File

@ -47,6 +47,7 @@
<Filter>Screens</Filter>
</ClCompile>
<ClCompile Include="Store.cpp" />
<ClCompile Include="BackgroundAudio.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInfoCache.h" />
@ -94,10 +95,11 @@
<Filter>Screens</Filter>
</ClInclude>
<ClInclude Include="Store.h" />
<ClInclude Include="BackgroundAudio.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Screens">
<UniqueIdentifier>{faee5dce-633b-4ba6-b19d-ea70ee3c1c38}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View File

@ -279,6 +279,7 @@ LOCAL_MODULE := ppsspp_jni
LOCAL_SRC_FILES := \
$(EXEC_AND_LIB_FILES) \
$(SRC)/native/android/app-android.cpp \
$(SRC)/UI/BackgroundAudio.cpp \
$(SRC)/UI/DevScreens.cpp \
$(SRC)/UI/EmuScreen.cpp \
$(SRC)/UI/MainScreen.cpp \

2
native

@ -1 +1 @@
Subproject commit bddebfceebd1b8e4c57ac300c4deddb526cdea08
Subproject commit 8685d02e6d44cbe327ab49f69efbcc1275771d6f