## Sports Development ## Media Kit (Media Services)
Foreword
Maintaining a steady rhythm during exercise is crucial for enhancing the effectiveness of your workout. Whether you're running, cycling, or engaging in high-intensity interval training (HIIT), a precise metronome can help you better control your exercise rhythm, thereby achieving better training results. This article will delve into how to develop a sports metronome, combining practical HarmonyOS development experience, allowing you to easily master the rhythm during exercise.
I. Why Choose SoundPool Over AVPlayer
When developing the sports metronome, we opted for SoundPool
instead of AVPlayer
. This is because SoundPool
excels at playing short, sharp提示 sounds, capable of responding quickly and ensuring the timely playback of sound effects, which is vital for a sports metronome that requires precise rhythm control. In contrast, AVPlayer
is more suitable for playing long audio files, such as music or videos, and its responsiveness and immediacy in sound effect playback are not as good as SoundPool
.
II. Core Logic of the Sports Metronome
- Initializing Sound Effects
Before the metronome starts, we need to load the sound effect files and initialize the SoundPool
. Below is the core code for initializing sound effects:
async initSound() {
this.soundPool = await media.createSoundPool(1, {
usage: audio.StreamUsage.STREAM_USAGE_MUSIC, // Audio stream usage type: music
rendererFlags: 1
});
const context = getContext(this) as common.UIAbilityContext;
const fd = context.resourceManager.getRawFdSync('medias/metronome2.mp3'); // It is recommended to use a short "tick" sound
this.soundId = await this.soundPool.load(
fd.fd,
fd.offset,
fd.length
);
}
- Metronome Playback Logic
The core logic of the metronome is to play sound effects at regular intervals based on the set BPM (beats per minute) and trigger visual cues (such as flashing) each time it plays. Below is the core code for the metronome playback logic:
startMetronome() {
if (this.isPlaying) return;
this.isPlaying = true;
const interval = 60000 / this.bpm; // Beat interval
const playWithFlash = () => {
this.flashActive = true;
setTimeout(() => this.flashActive = false, 100); // Set flashActive to false after 100 milliseconds to restore the visual state.
if (this.soundPool && this.soundId !== -1) {
this.soundPool.play(this.soundId, {
loop: 0,
rate: 1.0,
leftVolume: 1.0, // Maximum volume to ensure it can be heard during exercise
rightVolume: 1.0,
priority: 0
});
}
this.timerId = setTimeout(playWithFlash, interval);
};
playWithFlash();
}
- Stopping the Metronome
When stopping the metronome, we need to clear the timer and release the SoundPool
resources. Below is the core code for stopping the metronome:
stopMetronome() {
this.isPlaying = false;
clearTimeout(this.timerId);
}
III. User Interface Design
To allow users to conveniently control the metronome, we need to design a simple and intuitive user interface. Below is the core code for the user interface:
build() {
Column() {
// Large visual cue area
Circle()
.width(200)
.height(200)
.fill(this.flashActive ? Color.Red : Color.White)
.margin({ bottom: 40 })
.animation({ duration: 50, curve: Curve.EaseIn })
// Extra-large BPM display
Text(`${this.bpm}`)
.fontSize(60)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 30 })
// Sports-specific BPM range slider
Slider({
value: this.bpm,
min: 40, // Lowest effective sports rhythm
max: 200, // High-intensity interval training upper limit
step: 1
})
.width('90%')
.height(60)
.onChange((value: number) => {
this.bpm = value;
if (this.isPlaying) {
this.stopMetronome();
this.startMetronome();
}
})
// Sports-specific control button
Button(this.isPlaying ? 'Stop Exercise' : 'Start Exercise')
.width(200)
.height(80)
.fontSize(24)
.backgroundColor(this.isPlaying ? Color.Red : Color.Green)
.onClick(() => {
this.isPlaying ? this.stopMetronome() : this.startMetronome();
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
Key Points Analysis
Visual Cue: Implement visual beat cues using the
Circle
component and theflashActive
state.BPM Display: Display the current BPM value using the
Text
component, allowing users to intuitively see the beat frequency.BPM Adjustment: Allow users to adjust the BPM value using the
Slider
component, and automatically update the metronome frequency after adjustment.Control Button: Implement the start and stop functions of the metronome using the
Button
component.
IV. Optimization and Improvement
- Setting the Metronome Frequency Based on Exercise Step Frequency
To better adapt to the user's exercise rhythm, we can dynamically adjust the metronome frequency based on the user's step frequency. I previously wrote an article on how to obtain step frequency and stride length.
private async updateBpmFromStepFrequency() {
// Get the current step frequency
const currentStepFrequency = await this.getStepFrequency();
this.bpm = Math.round(currentStepFrequency * 60); // Convert step frequency to BPM
if (this.isPlaying) {
this.stopMetronome();
this.startMetronome();
}
}
- Adding Sound Effect Selection Functionality
To meet the needs of different users, we can add sound effect selection functionality, allowing users to choose different提示 sounds. For example, provide multiple sound effect files for users to choose from.
private soundOptions: string[] = ['metronome1.mp3', 'metronome2.mp3', 'metronome3.mp3'];
private selectedSoundIndex: number = 0;
private async loadSound() {
const context = getContext(this) as common.UIAbilityContext;
const fd = context.resourceManager.getRawFdSync(`medias/${this.soundOptions[this.selectedSoundIndex]}`);
this.soundId = await this.soundPool.load(
fd.fd,
fd.offset,
fd.length
);
}
- Optimizing Visual Cue Effects
To enhance the user experience, we can further optimize the visual cue effects, such as adding animation effects or changing the cue color.
Circle()
.width(200)
.height(200)
.fill(this.flashActive ? Color.Red : Color.White)
.margin({ bottom: 40 })
.animation({ duration: 100, curve: Curve.EaseInOut }) // Add animation effects
V. Summary
Using HarmonyOS's SoundPool
and related APIs, we can easily develop a powerful sports metronome.
Top comments (0)