Skip to content

Commit 220e3d0

Browse files
authored
Merge pull request #569 from scratchcpp/sound_effects
Implement sound effects
2 parents 23044db + 1596da9 commit 220e3d0

File tree

20 files changed

+596
-5
lines changed

20 files changed

+596
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ libscratchcpp::Project p("https://scratch.mit.edu/projects/XXXXXX");
124124

125125
- [x] Motion blocks
126126
- [x] Looks blocks
127-
- [ ] Sound blocks
127+
- [x] Sound blocks
128128
- [x] Event blocks
129129
- [x] Control blocks
130130
- [ ] Sensing blocks

include/scratchcpp/sound.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class SoundPrivate;
1616
class LIBSCRATCHCPP_EXPORT Sound : public Asset
1717
{
1818
public:
19+
enum class Effect
20+
{
21+
Pitch,
22+
Pan
23+
};
24+
1925
Sound(const std::string &name, const std::string &id, const std::string &format);
2026
Sound(const Sound &) = delete;
2127
virtual ~Sound() { }
@@ -27,11 +33,12 @@ class LIBSCRATCHCPP_EXPORT Sound : public Asset
2733
void setSampleCount(int newSampleCount);
2834

2935
virtual void setVolume(double volume);
36+
virtual void setEffect(Effect effect, double value);
3037

3138
virtual void start();
3239
virtual void stop();
3340

34-
virtual bool isPlaying();
41+
virtual bool isPlaying() const;
3542

3643
Target *target() const;
3744
void setTarget(Target *target);

include/scratchcpp/target.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "global.h"
88
#include "spimpl.h"
99
#include "rect.h"
10+
#include "sound.h"
1011

1112
namespace libscratchcpp
1213
{
@@ -88,6 +89,11 @@ class LIBSCRATCHCPP_EXPORT Target
8889
double volume() const;
8990
void setVolume(double newVolume);
9091

92+
virtual double soundEffect(Sound::Effect effect) const;
93+
virtual void setSoundEffect(Sound::Effect effect, double value);
94+
95+
virtual void clearSoundEffects();
96+
9197
virtual Rect boundingRect() const;
9298
virtual Rect fastBoundingRect() const;
9399

src/audio/iaudioplayer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class IAudioPlayer
1616
virtual float volume() const = 0;
1717
virtual void setVolume(float volume) = 0;
1818

19+
virtual float pitch() const = 0;
20+
virtual void setPitch(float pitch) = 0;
21+
22+
virtual float pan() const = 0;
23+
virtual void setPan(float pan) = 0;
24+
1925
virtual bool isLoaded() const = 0;
2026

2127
virtual void start() = 0;

src/audio/internal/audioplayer.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ bool AudioPlayer::load(unsigned int size, const void *data, unsigned long sample
5858

5959
m_loaded = true;
6060
ma_sound_set_volume(m_sound, m_volume);
61+
ma_sound_set_pitch(m_sound, m_pitch);
62+
ma_sound_set_pan(m_sound, m_pan);
6163
return true;
6264
}
6365

@@ -81,6 +83,8 @@ bool AudioPlayer::loadCopy(IAudioPlayer *player)
8183
m_loaded = true;
8284
m_copy = true;
8385
ma_sound_set_volume(m_sound, m_volume);
86+
ma_sound_set_pitch(m_sound, m_pitch);
87+
ma_sound_set_pan(m_sound, m_pan);
8488
return true;
8589
}
8690

@@ -99,6 +103,44 @@ void AudioPlayer::setVolume(float volume)
99103
ma_sound_set_volume(m_sound, volume);
100104
}
101105

106+
float AudioPlayer::pitch() const
107+
{
108+
return m_pitch;
109+
}
110+
111+
void AudioPlayer::setPitch(float pitch)
112+
{
113+
/*
114+
* 0.5 -> 220 Hz
115+
* 1 -> 440 Hz
116+
* 2 -> 880 Hz
117+
* 4 -> 1760 Hz
118+
* ...
119+
*/
120+
m_pitch = pitch;
121+
122+
if (!m_loaded)
123+
return;
124+
125+
ma_sound_set_pitch(m_sound, pitch);
126+
}
127+
128+
float AudioPlayer::pan() const
129+
{
130+
return m_pan;
131+
}
132+
133+
void AudioPlayer::setPan(float pan)
134+
{
135+
// -1 ... 0 ... 1
136+
m_pan = pan;
137+
138+
if (!m_loaded)
139+
return;
140+
141+
ma_sound_set_pan(m_sound, pan);
142+
}
143+
102144
bool AudioPlayer::isLoaded() const
103145
{
104146
return m_loaded;

src/audio/internal/audioplayer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ class AudioPlayer : public IAudioPlayer
2222
float volume() const override;
2323
void setVolume(float volume) override;
2424

25+
float pitch() const override;
26+
void setPitch(float pitch) override;
27+
28+
float pan() const override;
29+
void setPan(float pan) override;
30+
2531
bool isLoaded() const override;
2632

2733
void start() override;
@@ -36,6 +42,8 @@ class AudioPlayer : public IAudioPlayer
3642
bool m_copy = false;
3743
bool m_started = false;
3844
float m_volume = 1;
45+
float m_pitch = 1;
46+
float m_pan = 0;
3947
};
4048

4149
} // namespace libscratchcpp

src/audio/internal/audioplayerstub.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ void AudioPlayerStub::setVolume(float volume)
2828
m_volume = volume;
2929
}
3030

31+
float AudioPlayerStub::pitch() const
32+
{
33+
return m_pitch;
34+
}
35+
36+
void AudioPlayerStub::setPitch(float pitch)
37+
{
38+
m_pitch = pitch;
39+
}
40+
41+
float AudioPlayerStub::pan() const
42+
{
43+
return m_pan;
44+
}
45+
46+
void AudioPlayerStub::setPan(float pan)
47+
{
48+
m_pan = pan;
49+
}
50+
3151
bool AudioPlayerStub::isLoaded() const
3252
{
3353
return true;

src/audio/internal/audioplayerstub.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ class AudioPlayerStub : public IAudioPlayer
1818
float volume() const override;
1919
void setVolume(float volume) override;
2020

21+
float pitch() const override;
22+
void setPitch(float pitch) override;
23+
24+
float pan() const override;
25+
void setPan(float pan) override;
26+
2127
bool isLoaded() const override;
2228

2329
void start() override;
@@ -27,6 +33,8 @@ class AudioPlayerStub : public IAudioPlayer
2733

2834
private:
2935
float m_volume = 1;
36+
float m_pitch = 1;
37+
float m_pan = 0;
3038
};
3139

3240
} // namespace libscratchcpp

src/blocks/soundblocks.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <scratchcpp/compiler.h>
55
#include <scratchcpp/target.h>
66
#include <scratchcpp/input.h>
7+
#include <scratchcpp/field.h>
78
#include <scratchcpp/sound.h>
89

910
#include "soundblocks.h"
@@ -33,7 +34,10 @@ void SoundBlocks::registerBlocks(IEngine *engine)
3334
engine->addCompileFunction(this, "sound_play", &compilePlay);
3435
engine->addCompileFunction(this, "sound_playuntildone", &compilePlayUntilDone);
3536
engine->addCompileFunction(this, "sound_stopallsounds", &compileStopAllSounds);
37+
engine->addCompileFunction(this, "sound_seteffectto", &compileSetEffectTo);
38+
engine->addCompileFunction(this, "sound_changeeffectby", &compileChangeEffectBy);
3639
engine->addCompileFunction(this, "sound_changevolumeby", &compileChangeVolumeBy);
40+
engine->addCompileFunction(this, "sound_cleareffects", &compileClearEffects);
3741
engine->addCompileFunction(this, "sound_setvolumeto", &compileSetVolumeTo);
3842
engine->addCompileFunction(this, "sound_volume", &compileVolume);
3943

@@ -42,7 +46,15 @@ void SoundBlocks::registerBlocks(IEngine *engine)
4246

4347
// Inputs
4448
engine->addInput(this, "SOUND_MENU", SOUND_MENU);
49+
engine->addInput(this, "VALUE", VALUE);
4550
engine->addInput(this, "VOLUME", VOLUME);
51+
52+
// Fields
53+
engine->addField(this, "EFFECT", EFFECT);
54+
55+
// Field values
56+
engine->addFieldValue(this, "PITCH", PITCH);
57+
engine->addFieldValue(this, "PAN", PAN);
4658
}
4759

4860
void SoundBlocks::onInit(IEngine *engine)
@@ -118,6 +130,51 @@ void SoundBlocks::compileStopAllSounds(Compiler *compiler)
118130
compiler->addFunctionCall(&stopAllSounds);
119131
}
120132

133+
void SoundBlocks::compileSetEffectTo(Compiler *compiler)
134+
{
135+
compiler->addInput(VALUE);
136+
int option = compiler->field(EFFECT)->specialValueId();
137+
138+
switch (option) {
139+
case PITCH:
140+
compiler->addFunctionCall(&setPitchEffectTo);
141+
break;
142+
143+
case PAN:
144+
compiler->addFunctionCall(&setPanEffectTo);
145+
break;
146+
147+
default:
148+
assert(false);
149+
break;
150+
}
151+
}
152+
153+
void SoundBlocks::compileChangeEffectBy(Compiler *compiler)
154+
{
155+
compiler->addInput(VALUE);
156+
int option = compiler->field(EFFECT)->specialValueId();
157+
158+
switch (option) {
159+
case PITCH:
160+
compiler->addFunctionCall(&changePitchEffectBy);
161+
break;
162+
163+
case PAN:
164+
compiler->addFunctionCall(&changePanEffectBy);
165+
break;
166+
167+
default:
168+
assert(false);
169+
break;
170+
}
171+
}
172+
173+
void SoundBlocks::compileClearEffects(Compiler *compiler)
174+
{
175+
compiler->addFunctionCall(&clearEffects);
176+
}
177+
121178
void SoundBlocks::compileChangeVolumeBy(Compiler *compiler)
122179
{
123180
compiler->addInput(VOLUME);
@@ -296,6 +353,46 @@ unsigned int SoundBlocks::stopAllSounds(VirtualMachine *vm)
296353
return 0;
297354
}
298355

356+
unsigned int SoundBlocks::setPitchEffectTo(VirtualMachine *vm)
357+
{
358+
if (Target *target = vm->target())
359+
target->setSoundEffect(Sound::Effect::Pitch, vm->getInput(0, 1)->toDouble());
360+
361+
return 1;
362+
}
363+
364+
unsigned int SoundBlocks::setPanEffectTo(VirtualMachine *vm)
365+
{
366+
if (Target *target = vm->target())
367+
target->setSoundEffect(Sound::Effect::Pan, vm->getInput(0, 1)->toDouble());
368+
369+
return 1;
370+
}
371+
372+
unsigned int SoundBlocks::changePitchEffectBy(VirtualMachine *vm)
373+
{
374+
if (Target *target = vm->target())
375+
target->setSoundEffect(Sound::Effect::Pitch, target->soundEffect(Sound::Effect::Pitch) + vm->getInput(0, 1)->toDouble());
376+
377+
return 1;
378+
}
379+
380+
unsigned int SoundBlocks::changePanEffectBy(VirtualMachine *vm)
381+
{
382+
if (Target *target = vm->target())
383+
target->setSoundEffect(Sound::Effect::Pan, target->soundEffect(Sound::Effect::Pan) + vm->getInput(0, 1)->toDouble());
384+
385+
return 1;
386+
}
387+
388+
unsigned int SoundBlocks::clearEffects(VirtualMachine *vm)
389+
{
390+
if (Target *target = vm->target())
391+
target->clearSoundEffects();
392+
393+
return 0;
394+
}
395+
299396
unsigned int SoundBlocks::changeVolumeBy(VirtualMachine *vm)
300397
{
301398
if (Target *target = vm->target())

src/blocks/soundblocks.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,19 @@ class SoundBlocks : public IBlockSection
2020
enum Inputs
2121
{
2222
SOUND_MENU,
23+
VALUE,
2324
VOLUME
2425
};
2526

2627
enum Fields
2728
{
28-
29+
EFFECT
2930
};
3031

3132
enum FieldValues
3233
{
33-
34+
PITCH,
35+
PAN
3436
};
3537

3638
std::string name() const override;
@@ -42,6 +44,9 @@ class SoundBlocks : public IBlockSection
4244
static void compilePlay(Compiler *compiler);
4345
static void compilePlayUntilDone(Compiler *compiler);
4446
static void compileStopAllSounds(Compiler *compiler);
47+
static void compileSetEffectTo(Compiler *compiler);
48+
static void compileChangeEffectBy(Compiler *compiler);
49+
static void compileClearEffects(Compiler *compiler);
4550
static void compileChangeVolumeBy(Compiler *compiler);
4651
static void compileSetVolumeTo(Compiler *compiler);
4752
static void compileVolume(Compiler *compiler);
@@ -62,6 +67,12 @@ class SoundBlocks : public IBlockSection
6267

6368
static unsigned int stopAllSounds(VirtualMachine *vm);
6469

70+
static unsigned int setPitchEffectTo(VirtualMachine *vm);
71+
static unsigned int setPanEffectTo(VirtualMachine *vm);
72+
static unsigned int changePitchEffectBy(VirtualMachine *vm);
73+
static unsigned int changePanEffectBy(VirtualMachine *vm);
74+
static unsigned int clearEffects(VirtualMachine *vm);
75+
6576
static unsigned int changeVolumeBy(VirtualMachine *vm);
6677
static unsigned int setVolumeTo(VirtualMachine *vm);
6778
static unsigned int volume(VirtualMachine *vm);

0 commit comments

Comments
 (0)