Skip to content

Commit 0c52743

Browse files
committed
Implement sensing_loudness block
1 parent 4993b4e commit 0c52743

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

src/blocks/sensingblocks.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
#include "sensingblocks.h"
1515

1616
#include "../engine/internal/clock.h"
17+
#include "audio/audioinput.h"
18+
#include "audio/iaudioloudness.h"
1719

1820
using namespace libscratchcpp;
1921

2022
IClock *SensingBlocks::clock = nullptr;
23+
IAudioInput *SensingBlocks::audioInput = nullptr;
2124

2225
std::string SensingBlocks::name() const
2326
{
@@ -35,6 +38,7 @@ void SensingBlocks::registerBlocks(IEngine *engine)
3538
engine->addCompileFunction(this, "sensing_mousex", &compileMouseX);
3639
engine->addCompileFunction(this, "sensing_mousey", &compileMouseY);
3740
engine->addCompileFunction(this, "sensing_setdragmode", &compileSetDragMode);
41+
engine->addCompileFunction(this, "sensing_loudness", &compileLoudness);
3842
engine->addCompileFunction(this, "sensing_timer", &compileTimer);
3943
engine->addCompileFunction(this, "sensing_resettimer", &compileResetTimer);
4044
engine->addCompileFunction(this, "sensing_of", &compileOf);
@@ -45,6 +49,7 @@ void SensingBlocks::registerBlocks(IEngine *engine)
4549
engine->addMonitorNameFunction(this, "sensing_mousedown", &mouseDownMonitorName);
4650
engine->addMonitorNameFunction(this, "sensing_mousex", &mouseXMonitorName);
4751
engine->addMonitorNameFunction(this, "sensing_mousey", &mouseYMonitorName);
52+
engine->addMonitorNameFunction(this, "sensing_loudness", &loudnessMonitorName);
4853
engine->addMonitorNameFunction(this, "sensing_timer", &timerMonitorName);
4954
engine->addMonitorNameFunction(this, "sensing_current", &currentMonitorName);
5055
engine->addMonitorNameFunction(this, "sensing_dayssince2000", &daysSince2000MonitorName);
@@ -156,6 +161,11 @@ void SensingBlocks::compileSetDragMode(Compiler *compiler)
156161
}
157162
}
158163

164+
void SensingBlocks::compileLoudness(Compiler *compiler)
165+
{
166+
compiler->addFunctionCall(&loudness);
167+
}
168+
159169
void SensingBlocks::compileTimer(Compiler *compiler)
160170
{
161171
compiler->addFunctionCall(&timer);
@@ -354,6 +364,12 @@ const std::string &SensingBlocks::mouseYMonitorName(Block *block)
354364
return name;
355365
}
356366

367+
const std::string &SensingBlocks::loudnessMonitorName(Block *block)
368+
{
369+
static const std::string name = "loudness";
370+
return name;
371+
}
372+
357373
const std::string &SensingBlocks::timerMonitorName(Block *block)
358374
{
359375
static const std::string name = "timer";
@@ -453,6 +469,16 @@ unsigned int SensingBlocks::setNotDraggableMode(VirtualMachine *vm)
453469
return 0;
454470
}
455471

472+
unsigned int SensingBlocks::loudness(VirtualMachine *vm)
473+
{
474+
if (!audioInput)
475+
audioInput = AudioInput::instance().get();
476+
477+
auto audioLoudness = audioInput->audioLoudness();
478+
vm->addReturnValue(audioLoudness->getLoudness());
479+
return 0;
480+
}
481+
456482
unsigned int SensingBlocks::distanceTo(VirtualMachine *vm)
457483
{
458484
Sprite *sprite = dynamic_cast<Sprite *>(vm->target());

src/blocks/sensingblocks.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace libscratchcpp
1212
{
1313

1414
class Target;
15+
class IAudioInput;
1516

1617
/*! \brief The SensingBlocks class contains the implementation of sensing blocks. */
1718
class SensingBlocks : public IBlockSection
@@ -66,6 +67,7 @@ class SensingBlocks : public IBlockSection
6667
static void compileMouseX(Compiler *compiler);
6768
static void compileMouseY(Compiler *compiler);
6869
static void compileSetDragMode(Compiler *compiler);
70+
static void compileLoudness(Compiler *compiler);
6971
static void compileTimer(Compiler *compiler);
7072
static void compileResetTimer(Compiler *compiler);
7173
static void compileOf(Compiler *compiler);
@@ -75,6 +77,7 @@ class SensingBlocks : public IBlockSection
7577
static const std::string &mouseDownMonitorName(Block *block);
7678
static const std::string &mouseXMonitorName(Block *block);
7779
static const std::string &mouseYMonitorName(Block *block);
80+
static const std::string &loudnessMonitorName(Block *block);
7881
static const std::string &timerMonitorName(Block *block);
7982
static const std::string &currentMonitorName(Block *block);
8083
static const std::string &daysSince2000MonitorName(Block *block);
@@ -87,6 +90,8 @@ class SensingBlocks : public IBlockSection
8790
static unsigned int setDraggableMode(VirtualMachine *vm);
8891
static unsigned int setNotDraggableMode(VirtualMachine *vm);
8992

93+
static unsigned int loudness(VirtualMachine *vm);
94+
9095
static unsigned int distanceTo(VirtualMachine *vm);
9196
static unsigned int distanceToByIndex(VirtualMachine *vm);
9297
static unsigned int distanceToMousePointer(VirtualMachine *vm);
@@ -128,6 +133,7 @@ class SensingBlocks : public IBlockSection
128133
static unsigned int daysSince2000(VirtualMachine *vm);
129134

130135
static IClock *clock;
136+
static IAudioInput *audioInput;
131137

132138
private:
133139
struct Question

test/blocks/sensing_blocks_test.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <enginemock.h>
1010
#include <timermock.h>
1111
#include <clockmock.h>
12+
#include <audioinputmock.h>
13+
#include <audioloudnessmock.h>
1214

1315
#include "../common.h"
1416
#include "blocks/sensingblocks.h"
@@ -129,6 +131,7 @@ TEST_F(SensingBlocksTest, RegisterBlocks)
129131
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_mousex", &SensingBlocks::compileMouseX));
130132
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_mousey", &SensingBlocks::compileMouseY));
131133
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_setdragmode", &SensingBlocks::compileSetDragMode));
134+
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_loudness", &SensingBlocks::compileLoudness));
132135
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_timer", &SensingBlocks::compileTimer));
133136
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_resettimer", &SensingBlocks::compileResetTimer));
134137
EXPECT_CALL(m_engineMock, addCompileFunction(m_section.get(), "sensing_of", &SensingBlocks::compileOf));
@@ -139,6 +142,7 @@ TEST_F(SensingBlocksTest, RegisterBlocks)
139142
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "sensing_mousedown", &SensingBlocks::mouseDownMonitorName));
140143
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "sensing_mousex", &SensingBlocks::mouseXMonitorName));
141144
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "sensing_mousey", &SensingBlocks::mouseYMonitorName));
145+
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "sensing_loudness", &SensingBlocks::loudnessMonitorName));
142146
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "sensing_timer", &SensingBlocks::timerMonitorName));
143147
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "sensing_current", &SensingBlocks::currentMonitorName));
144148
EXPECT_CALL(m_engineMock, addMonitorNameFunction(m_section.get(), "sensing_dayssince2000", &SensingBlocks::daysSince2000MonitorName));
@@ -741,6 +745,65 @@ TEST_F(SensingBlocksTest, SetDragModeImpl)
741745
ASSERT_FALSE(sprite.draggable());
742746
}
743747

748+
TEST_F(SensingBlocksTest, Loudness)
749+
{
750+
Compiler compiler(&m_engineMock);
751+
752+
auto block = std::make_shared<Block>("a", "sensing_loudness");
753+
754+
EXPECT_CALL(m_engineMock, functionIndex(&SensingBlocks::loudness)).WillOnce(Return(0));
755+
compiler.init();
756+
757+
compiler.setBlock(block);
758+
SensingBlocks::compileLoudness(&compiler);
759+
760+
compiler.end();
761+
762+
ASSERT_EQ(compiler.bytecode(), std::vector<unsigned int>({ vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT }));
763+
ASSERT_TRUE(compiler.constValues().empty());
764+
}
765+
766+
TEST_F(SensingBlocksTest, LoudnessMonitorName)
767+
{
768+
ASSERT_EQ(SensingBlocks::loudnessMonitorName(nullptr), "loudness");
769+
}
770+
771+
TEST_F(SensingBlocksTest, LoudnessImpl)
772+
{
773+
static unsigned int bytecode[] = { vm::OP_START, vm::OP_EXEC, 0, vm::OP_HALT };
774+
static BlockFunc functions[] = { &SensingBlocks::loudness };
775+
776+
VirtualMachine vm(nullptr, &m_engineMock, nullptr);
777+
vm.setFunctions(functions);
778+
779+
vm.setBytecode(bytecode);
780+
vm.run();
781+
782+
ASSERT_EQ(vm.registerCount(), 1);
783+
784+
AudioInputMock audioInput;
785+
auto audioLoudness = std::make_shared<AudioLoudnessMock>();
786+
SensingBlocks::audioInput = &audioInput;
787+
788+
EXPECT_CALL(audioInput, audioLoudness()).WillOnce(Return(audioLoudness));
789+
EXPECT_CALL(*audioLoudness, getLoudness()).WillOnce(Return(-1));
790+
vm.reset();
791+
vm.run();
792+
793+
ASSERT_EQ(vm.registerCount(), 1);
794+
ASSERT_EQ(vm.getInput(0, 1)->toDouble(), -1);
795+
796+
EXPECT_CALL(audioInput, audioLoudness()).WillOnce(Return(audioLoudness));
797+
EXPECT_CALL(*audioLoudness, getLoudness()).WillOnce(Return(62));
798+
vm.reset();
799+
vm.run();
800+
801+
ASSERT_EQ(vm.registerCount(), 1);
802+
ASSERT_EQ(vm.getInput(0, 1)->toDouble(), 62);
803+
804+
SensingBlocks::audioInput = nullptr;
805+
}
806+
744807
TEST_F(SensingBlocksTest, Timer)
745808
{
746809
Compiler compiler(&m_engineMock);

0 commit comments

Comments
 (0)