Skip to content

Commit 9c31543

Browse files
committed
core: Store Sound data as SwfSlice instead of copied vecs
1 parent f95e07f commit 9c31543

File tree

3 files changed

+46
-30
lines changed

3 files changed

+46
-30
lines changed

core/src/backend/audio.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ use crate::{
44
buffer::Substream,
55
context::UpdateContext,
66
display_object::{self, DisplayObject, MovieClip, TDisplayObject},
7+
tag_utils::SwfMovie,
78
};
89
use downcast_rs::Downcast;
910
use gc_arena::Collect;
1011
use slotmap::{new_key_type, Key, SlotMap};
12+
use std::sync::Arc;
1113

1214
#[cfg(feature = "audio")]
1315
pub mod decoders;
@@ -88,7 +90,7 @@ pub trait AudioBackend: Downcast {
8890
fn pause(&mut self);
8991

9092
/// Registers an sound embedded in an SWF.
91-
fn register_sound(&mut self, swf_sound: &swf::Sound) -> Result<SoundHandle, RegisterError>;
93+
fn register_sound(&mut self, movie: Arc<SwfMovie>, swf_sound: &swf::Sound) -> Result<SoundHandle, RegisterError>;
9294

9395
/// Registers MP3 audio from an external source.
9496
fn register_mp3(&mut self, data: &[u8]) -> Result<SoundHandle, DecodeError>;
@@ -225,7 +227,7 @@ impl NullAudioBackend {
225227
impl AudioBackend for NullAudioBackend {
226228
fn play(&mut self) {}
227229
fn pause(&mut self) {}
228-
fn register_sound(&mut self, sound: &swf::Sound) -> Result<SoundHandle, RegisterError> {
230+
fn register_sound(&mut self, _movie: Arc<SwfMovie>, sound: &swf::Sound) -> Result<SoundHandle, RegisterError> {
229231
// Slice off latency seek for MP3 data.
230232
let data = if sound.format.compression == swf::AudioCompression::Mp3 {
231233
sound.data.get(2..).ok_or(RegisterError::ShortMp3)?

core/src/backend/audio/mixer.rs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::decoders::{self, AdpcmDecoder, Decoder, PcmDecoder, SeekableDecoder};
22
use super::{SoundHandle, SoundInstanceHandle, SoundStreamInfo, SoundTransform};
33
use crate::backend::audio::{DecodeError, RegisterError};
44
use crate::buffer::Substream;
5-
use crate::tag_utils::SwfSlice;
5+
use crate::tag_utils::{SwfMovie, SwfSlice};
66
use slotmap::SlotMap;
77
use std::io::Cursor;
88
use std::sync::{Arc, Mutex, RwLock};
@@ -137,6 +137,37 @@ impl<D: Decoder> dasp::signal::Signal for DecoderStream<D> {
137137
}
138138
}
139139

140+
#[derive(Clone)]
141+
enum SoundData {
142+
Owned(Arc<[u8]>),
143+
Movie(SwfSlice),
144+
}
145+
146+
impl SoundData {
147+
pub fn len(&self) -> usize {
148+
match self {
149+
Self::Owned(data) => data.len(),
150+
Self::Movie(data) => data.len(),
151+
}
152+
}
153+
}
154+
155+
impl AsRef<[u8]> for SoundData {
156+
#[inline]
157+
fn as_ref(&self) -> &[u8] {
158+
match self {
159+
Self::Owned(data) => &data,
160+
Self::Movie(data) => data.as_ref(),
161+
}
162+
}
163+
}
164+
165+
// Needed for `AdpcmDecoder<std::io::Cursor<mixer::SoundData>>: SeekableDecoder` :(
166+
impl Default for SoundData {
167+
fn default() -> Self {
168+
Self::Owned(Arc::new([]))
169+
}
170+
}
140171
/// Contains the data and metadata for a sound in an SWF file.
141172
///
142173
/// A sound is defined by the `DefineSound` SWF tags and contains the audio data for the sound.
@@ -147,7 +178,7 @@ struct Sound {
147178
/// The audio data of this sound.
148179
///
149180
/// This will be compressed in the format indicated by `format.compression`.
150-
data: Arc<[u8]>,
181+
data: SoundData,
151182

152183
/// Number of samples in this audio.
153184
/// This does not include `skip_sample_frames`.
@@ -295,7 +326,7 @@ impl AudioMixer {
295326
/// * ActionScript sounds that may have a custom start and loop setting
296327
fn make_seekable_decoder(
297328
format: &swf::SoundFormat,
298-
data: Cursor<ArcAsRef>,
329+
data: Cursor<SoundData>,
299330
) -> Result<Box<dyn SeekableDecoder>, decoders::Error> {
300331
let decoder: Box<dyn SeekableDecoder> = match format.compression {
301332
AudioCompression::UncompressedUnknownEndian => {
@@ -354,7 +385,7 @@ impl AudioMixer {
354385
&self,
355386
sound: &Sound,
356387
settings: &swf::SoundInfo,
357-
data: Cursor<ArcAsRef>,
388+
data: Cursor<SoundData>,
358389
) -> Result<Box<dyn Stream>, DecodeError> {
359390
// Instantiate a decoder for the compression that the sound data uses.
360391
let decoder = Self::make_seekable_decoder(&sound.format, data)?;
@@ -505,7 +536,7 @@ impl AudioMixer {
505536
}
506537

507538
/// Registers an embedded SWF sound with the audio mixer.
508-
pub fn register_sound(&mut self, swf_sound: &swf::Sound) -> Result<SoundHandle, RegisterError> {
539+
pub fn register_sound(&mut self, movie: Arc<SwfMovie>, swf_sound: &swf::Sound) -> Result<SoundHandle, RegisterError> {
509540
// Slice off latency seek for MP3 data.
510541
let (skip_sample_frames, data) = if swf_sound.format.compression == AudioCompression::Mp3 {
511542
if swf_sound.data.len() < 2 {
@@ -519,7 +550,7 @@ impl AudioMixer {
519550

520551
let sound = Sound {
521552
format: swf_sound.format.clone(),
522-
data: Arc::from(data),
553+
data: SoundData::Movie(SwfSlice::new(movie, data)),
523554
num_sample_frames: swf_sound.num_samples,
524555
skip_sample_frames,
525556
};
@@ -539,7 +570,7 @@ impl AudioMixer {
539570
is_stereo: true,
540571
is_16_bit: true,
541572
},
542-
data,
573+
data: SoundData::Owned(data),
543574
num_sample_frames: metadata.num_sample_frames,
544575
skip_sample_frames: 0,
545576
};
@@ -579,7 +610,7 @@ impl AudioMixer {
579610
settings: &swf::SoundInfo,
580611
) -> Result<SoundInstanceHandle, DecodeError> {
581612
let sound = &self.sounds[sound_handle];
582-
let data = Cursor::new(ArcAsRef(Arc::clone(&sound.data)));
613+
let data = Cursor::new(sound.data.clone());
583614
// Create a stream that decodes and resamples the sound.
584615
let stream = if sound.skip_sample_frames == 0
585616
&& settings.in_sample.is_none()
@@ -760,23 +791,6 @@ impl AudioMixerProxy {
760791
}
761792
}
762793

763-
/// A dummy wrapper struct to implement `AsRef<[u8]>` for `Arc<Vec<u8>>`.
764-
/// Not having this trait causes problems when trying to use `Cursor<Vec<u8>>`.
765-
struct ArcAsRef(Arc<[u8]>);
766-
767-
impl AsRef<[u8]> for ArcAsRef {
768-
#[inline]
769-
fn as_ref(&self) -> &[u8] {
770-
&self.0
771-
}
772-
}
773-
774-
impl Default for ArcAsRef {
775-
fn default() -> Self {
776-
ArcAsRef(Arc::new([]))
777-
}
778-
}
779-
780794
/// A stream for event sound instances with custom envelopes, start/end point, or loop settings.
781795
struct EventSoundStream {
782796
decoder: Box<dyn SeekableDecoder>,
@@ -1069,8 +1083,8 @@ impl dasp::signal::Signal for EnvelopeSignal {
10691083
macro_rules! impl_audio_mixer_backend {
10701084
($mixer:ident) => {
10711085
#[inline]
1072-
fn register_sound(&mut self, swf_sound: &swf::Sound) -> Result<SoundHandle, RegisterError> {
1073-
self.$mixer.register_sound(swf_sound)
1086+
fn register_sound(&mut self, movie: std::sync::Arc<$crate::tag_utils::SwfMovie>, swf_sound: &swf::Sound) -> Result<SoundHandle, RegisterError> {
1087+
self.$mixer.register_sound(movie, swf_sound)
10741088
}
10751089

10761090
#[inline]

core/src/display_object/movie_clip.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4008,7 +4008,7 @@ impl<'gc, 'a> MovieClipData<'gc> {
40084008
reader: &mut SwfStream<'a>,
40094009
) -> Result<(), Error> {
40104010
let sound = reader.read_define_sound()?;
4011-
if let Ok(handle) = context.audio.register_sound(&sound) {
4011+
if let Ok(handle) = context.audio.register_sound(self.movie(), &sound) {
40124012
context
40134013
.library
40144014
.library_for_movie_mut(self.movie())

0 commit comments

Comments
 (0)