1. Trang chủ
  2. » Công Nghệ Thông Tin

Học Actionscript 3.0 - p 33 ppsx

10 330 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Internal and External Sounds
Trường học University of Information Technology
Chuyên ngành Computer Science
Thể loại Bài giảng
Năm xuất bản 2023
Thành phố Ho Chi Minh City
Định dạng
Số trang 10
Dung lượng 4,91 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

This creation of a Sound class instance and the use of one method to load a sound file are the only basic differences between using internal and external sounds.. To load a sound from a

Trang 1

Internal and External Sounds

Once you’ve provided a linkage class name, you can create an instance of the

sound the same way you instantiate a movie clip:

var snd:Sound = new ClaireElmo();

Thereafter, you can manage the instance of this sound by referring to the

vari-able snd This creation of a Sound class instance and the use of one method

to load a sound file are the only basic differences between using internal and

external sounds All play, pause, stop, and transform operations are identical,

regardless of the sound source

If you prefer to use internal sounds, the using_internal_sound.fla source file

demonstrates the playing and stopping of a short imported sound using the

basic syntax explained in the “Playing, Stopping, and Pausing Sounds”

sec-tion later in this chapter However, we recommend using external sounds for

most uses

Loading External Sounds

Using internal sounds, creating an instance of the Sound class and populating

it with audio occur in one step To load a sound from an external MP3, we

need to use the load() method of the Sound class, so we must first explicitly

create an instance of the class This is shown in line 1 of the following code,

found in the loading_external_sound.fla source file

1 var snd:Sound = new Sound();

2

3 var req:URLRequest = new URLRequest( "song.mp3" );

4 snd.load(req);

As discussed in prior chapters, you also need to create an instance of the

URLRequest class (line 3) any time you load something Although it has

addi-tional purposes for advanced URL processing, the URLRequest class is also

used to standardize the loading process This allows you to load many asset

types in a consistent manner Finally, we load the sound in line 4

Once you’ve completed this process, you’re again ready to start manipulating

the snd instance When working with external sounds, however, there are

additional factors that warrant a little extra attention The steps we’ll describe

aren’t required, but they’re recommended You’ll find that they improve not

only your own development efforts (such as when listening for errors when

loading a sound), but also the user experience (such as providing feedback

during loading)

It’s not uncommon when loading external assets to encounter a missing file

problem The path to the file may be old or incorrect, or the loaded asset or

your SWF may have been moved In this case, a runtime error like this may

occur:

Error #2044: Unhandled IOErrorEvent:

text=Error #2032: Stream Error.

N OT E

Another difference between working with internal and external sounds is that you can buffer a loaded sound to improve playback experience Buffering

a sound means that your playback won’t begin until a specified amount of sound data has loaded This allows the back-ground loading of the rest of the sound

to stay ahead of your playback and is discussed in the “Buffering Sounds” sec-tion later in this chapter.

Trang 2

So, it’s a good idea to plan for this possibility and listen for an IO_ERROR

(input/output error) If you do encounter an error, you can present it to the viewer as part of the user experience (through an alert or warning icon, for example), or just try to correct it during the authoring process by tracing to the Output panel The following listener function traces a message, as well as the descriptive text sent with the event

5 //listen for error

6 snd.addEventListener(IOErrorEvent.IO_ERROR, onIOError,

7 false, 0, true);

8 function onIOError(evt:IOErrorEvent):void {

9 trace( "Error occurred when loading sound:" , evt.text);

10 } The next enhancement to include when working with external sounds is

to provide feedback to the user during the loading process Again we add a listener to the sound instance, this time listening for a PROGRESS event, which

is dispatched whenever loading progress occurs When this happens, you can update the user by, for example, increasing the width of a sprite to create a progress bar

Lines 12 through 24 of the following code create the progress bar Line 12 passes a color to the drawBar() function (lines 17 through 24), which creates

a sprite, draws a rectangle that is 1 pixel wide and 10 pixels tall, and returns the sprite Lines 13 and 14 position the progress bar and line 15 adds it to the display list

Lines 26 through 30 contain the listener function The event captured by the listener function carries with it information, including the total number of bytes in the target object (in this scenario the sound being loaded), as well as the number of bytes loaded at the moment the event was fired By dividing the latter by the former, you end up with a fraction For example, if 500 bytes

of a total 1,000 bytes have loaded, the progress is 500/1,000 or 0.5, indicating that the object is 50-percent loaded By multiplying with a desired width of the progress bar, the bar will increase to the final desired size when the file is 100-percent loaded

11 //track loading progress

12 var loadBar:Sprite = drawBar(0x000099);

13 loadBar.x = 20;

14 loadBar.y = 15;

15 addChild(loadBar);

16

17 function drawBar(col:uint):Sprite {

18 var bar:Sprite = new Sprite();

19 var g:Graphics = bar.graphics;

20 g.beginFill(col, 1);

21 g.drawRect(0, 0, 1, 10);

22 g.endFill();

23 return bar;

24 }

25

26 snd.addEventListener(ProgressEvent.PROGRESS, onLoadingProgress,

27 false, 0, true);

N OT E

In this example, the progress bar will

reach 100 pixels wide when the process

finishes or will stay at its original 1-pixel

width if the function fails Keeping these

start and finish sizes in mind when

test-ing locally is useful because loadtest-ing

even very large files from a local hard

drive happens very quickly, and it’s

quite common not to see the progress

bar move at all with small sound files.

Trang 3

Playing, Stopping, and Pausing Sounds

28 function onLoadingProgress(evt:ProgressEvent):void {

29 loadBar.width = 100 * (evt.bytesLoaded / evt.bytesTotal);

30 }

The last option we’ll introduce here is for responding to the completion of

the sound loading process The structure is similar to the prior two event

listener examples, this time using the Event.COMPLETE event to trigger the

listener function

31 //react to successful load

32 var sndLength:Number = 0;

33 snd.addEventListener(Event.COMPLETE, onCompleteLoad,

34 false, 0, true);

35 function onCompleteLoad(evt:Event):void {

36 sndLength = snd.length;

37 trace( "Sound length:" , sndLength);

38 }

After creating the variable in line 32, this example stores the length of the

sound in milliseconds in sndLength, and traces that value as a quick

indica-tion that the process is complete This code is the starting point for an audio

player exercise that runs throughout the chapter Soon, we’ll use the sound’s

length to update a progress bar during playback of the sound First, however,

let’s look closely at the playback syntax

Playing, Stopping, and Pausing Sounds

The simple syntax of the Sound class’s play() method can be a bit deceiving

because it’s only part of the picture To play a sound, all you need to do is call

the method from the Sound class instance However, all this does is start

play-back and, without additional infrastructure, you can’t do much else Instead,

you should play the sound into an instance of the SoundChannel class, which

allows you to stop, pan, or adjust the volume of the channel This is different

from prior versions of ActionScript, in which all sound control rested with

the Sound object.

To emphasize this idea, let’s think again about a recording studio To move a

sound from the left speaker to the right speaker in a mix, a sound engineer

would twist a knob at the mixing desk, not ask a musician to run from one

side of the studio to another Similarly, although musicians often handle

volume subtleties, fading a sound up or down is typically accomplished by

adjusting a sound channel’s volume slider In other words, the playback of

the sound is typically separated from the manipulation of that sound in the

mixing process The same is true in ActionScript 3.0

We’ll begin with simple examples and then we’ll add these features to our

ongoing audio player

Trang 4

Playing a Sound

To place a sound into a channel, all you need to do is create the channel and then set it equal to the result of the sound’s play() method.

var channel:SoundChannel; = new SoundChannel();

channel = snd.play();

This associates the sound with the specified channel, the same way you would plug a guitar into a channel in our metaphorical recording studio’s mixing desk Once the sound is in the channel, you’ll be able to adjust its volume, set its pan, and stop its playback—all of which we’ll discuss in a moment

But how soon can you play the sound? If you’re using imported audio files, you can typically play the sound right away However, when working with external files, you must consider the loading process If you invoke the load()

method to start loading an external sound file and then immediately attempt

to play the sound, your attempt will likely fail because the sound will prob-ably still be loading However, we saw in the previous section that a COMPLETE

event is dispatched when a Sound instance’s MP3 is finished loading So, an

event listener listening for that event can play the sound without any problem The following snippet shows syntax for playing a sound immediately after it’s loaded This snippet assumes a Sound instance of snd, and a SoundChannel

instance of channel.

snd.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true);

function onLoadComplete(evt:Event):void { channel = snd.play();

} This approach is used to play a sound as soon after loading as possible This

is useful for things like background audio that begins playing right away Perhaps the most common way to play a sound, however, is by clicking a but-ton or through similar user interaction We’ll set up just such a butbut-ton when

we return to our ongoing sound player project

Stopping a Sound

Stopping a single sound in a channel requires only the stop() method

Unlike playing the sound, however, this method is invoked from the channel, not from the sound itself Again assuming you’ve previously created a new instance of the SoundChannel, named channel, the syntax looks like this:

channel.stop();

It’s also possible to stop all sounds using the SoundMixer class As in the real

world, multichannel playback funnels through a master sound mixer Just as you can kill that master channel in a studio, you can stop all sounds using the SoundMixer class and it’s stopAll() method.

Trang 5

Playing, Stopping, and Pausing Sounds

Unlike the previous methods discussed, stopAll() is static This means an

instance of the SoundMixer class does not need to be created using the new

keyword Instead, the method is called directly from the class Therefore, to

stop playing the sounds in all channels, you need only write:

SoundMixer.stopAll();

Pausing Sounds and Resuming Playback

Pausing a sound is a bit different Currently, there is no dedicated pause

method in ActionScript 3.0 Instead, you must rely on an optional parameter

of the play() method that allows you to play the sound starting from a

par-ticular number of seconds offset from the beginning of the sound

To use this feature to pause playback, you must first store the current

posi-tion of a sound as it’s playing Having retrieved this value from the channel’s

aptly named position property, you can then stop playback in that channel

Later, you can resume playback by playing the sound from the stored

posi-tion Assuming the ongoing use of the snd and channel instance names, here

are the first and second steps of the process:

var pausePosition:Number = channel.position;

channel.stop();

Then, at some later point, you can resume playback from where you left off:

channel = snd.play(pausePosition);

Applying the Syntax

Now let’s put these concepts into practice and pick up from the source file we

started in the “Loading External Sounds” section The following code, added

to the previous example, forms the player_basic.fla source file.

If you want to look ahead, here’s a quick description of all the code related

to playing a sound, spanning lines 40 through 75, so we know what we’re

trying to accomplish Lines 44 through 54 contain an event listener that will

be triggered when a user clicks on the play button we’ll soon create Lines 56

through 65 include the code required to show a progress bar during playback

Finally, lines 67 through 75 contain the function triggered when the playback

is complete

Now let’s focus on the function that plays the sound and its accompanying

variables Line 40 creates a Boolean variable that we’ll use to check whether

the sound is already playing Because we’ll be using a button to play our

sound, it will now be possible to play the sound multiple times However,

this also means that rapid repeated clicks of the button will play the sound

over and over itself, layering the sound This is fine for simulating a musical

instrument or an echo, for which multiple simultaneous occurrences of the

sound are acceptable, but it’s less desirable for playing spoken dialog or other

sounds that typically would not be layered over themselves

N OT E

You can control the volume and pan of the master mix by using the

SoundMixer class, which we’ll dem-onstrate later on We’ll also use the

SoundMixer to visualize a sound during playback later in the chapter.

Trang 6

Line 41 creates a variable that will store the most recent playback position of the song in its channel, when the pause button is pressed Remember that we’re adding extra functionality to the play process to support pausing play-back, so we’ll need to pass this value to the play() method Because we’re

using one play() method to play from a stop and from a pause, it’s very

important to initialize the value of this variable to zero so that the sound starts playing at the beginning when first played Similarly, when we code the stop behavior later on, we’ll need to reset this variable to zero after stop-ping the sound, to avoid restarting from any previous pause position when replaying

Lines 44 through 54 make up the onPlaySound() function, which will be

called by a play button that we’ll add later on Line 45 checks to see whether

the sound is not already playing If that test passes, the isPlaying variable

is set to true to prevent the sound from playing more than once simultane-ously Lines 47 and 48 add a listener to the main timeline (the scope of the script) that will fire upon every enter frame event We’ll use this listener to update the playback progress bar in just a moment Lines 49 through 51 add

a listener to the channel to trigger when the sound playback is complete We’ll use that to reset things so the sound can be played again Finally, line 52 plays the sound The first time it plays, it will play from the beginning because of the initial 0 value of the soundPosition variable in line 41.

39 //play

40 var isPlaying:Boolean = false;

41 var soundPosition:Number = 0;

42 var channel:SoundChannel = new SoundChannel();

43

44 function onPlaySound(evt:MouseEvent):void {

45 if (!isPlaying) {

46 isPlaying = true;

47 addEventListener(Event.ENTER_FRAME, onPlayProgress,

48 false, 0, true);

49 channel.addEventListener(Event.SOUND_COMPLETE,

50 onPlayComplete,

51 false, 0, true);

52 channel = snd.play(soundPosition);

53 }

54 } Next, we’ll setup the playback progress bar Lines 56 through 59 create the bar, position it and add it to the display list The drawBar() function is the

same function found earlier in the file, spanning lines 17 through 24 and discussed in the “Loading External Sounds” section earlier in this chapter It simply creates a sprite and draws a 1 × 10-pixel rectangle

The function in lines 61 through 65 updates the width of the progress bar It’s called every enter frame event because of the listener created in lines 47 and 48 Dividing the playback position of the sound in the channel by the total length

of the sound gives us a percentage For example, if the position is 5000 and the length of the sound clip is 10,000 milliseconds (10 seconds), the playback is

Trang 7

Playing, Stopping, and Pausing Sounds

50-percent complete That percentage is then multiplied by the desired width of

the bar, 100 pixels, and the width of the bar is set to this value

Later on in the chapter, we’ll drop two function calls into lines 63 and 64

to control the volume and pan of the sound, and we’ll update peak meter

graphics on the stage that show the amplitude of the sound during playback

55 //play progress bar

56 var playBar:Sprite = drawBar(0x0000FF);

57 playBar.x = 20;

58 playBar.y = 15;

59 addChild(playBar);

60

61 function onPlayProgress(evt:Event):void {

62 playBar.width = 100 * (channel.position / sndLength);

63 //future home of volume and pan adjustment

64 //future home of amplitude meter adjustment;

65 }

The onPlayComplete() listener function (added in line 48) is triggered after

the sound has finished playing Lines 68 and 69 remove both listeners added

when playback began Once the sound is finished playing, there is no longer

a need to update its playback progress or listen for a SOUND_COMPLETE event

Removing the listeners is not only efficient, but also allows us to set the

play-back progress bar width to 0 If not removed, the enter frame event would

continue to set the bar’s width to 100 (The position of the sound is at the end

of the file when playback is complete.)

The remainder of the function stops the sound, resets the soundPosition

variable to 0, the width of the play progress bar to 0, and the isPlaying

vari-able to false All of this allows us to play the sound anew

66 //playback complete listener function

67 function onPlayComplete(evt:Event):void {

68 removeEventListener(Event.ENTER_FRAME, onPlayProgress);

69 channel.removeEventListener(Event.SOUND_COMPLETE,

70 onPlayComplete);

71 channel.stop();

72 soundPosition = 0;

73 playBar.width = 0;

74 isPlaying = false;

75 }

Now that we have the play functionality complete, we need a button to

trig-ger it We’ll be creating three buttons by the time we’re done, so rather than

repeating the button creation code three times, let’s set up a function to do

the work for us This takes less code but, more importantly, it means that if a

future edit is required, you have to edit the code in only one place, not three

We’re going to draw our buttons dynamically, using the RoundRectButton

class we created in Chapter 8, so line 77 imports the class Remember that

this material is presented in chunks for clarity Import statements are

typical-ly consolidated at the top of your script and you should feel free to reorganize

your code any way you see fit

N OT E

One idea behind using the

RoundRectButton class to draw but-tons dynamically is to give you contin-ued practice using packages and classes However, you’ll also find when we’re done that this entire file will contain

no imported assets As such, the entire audio player is less than 5 KB! This is

a best-case scenario because we kept the interface simple—both so you didn’t need to rely on library assets and so a more complex interface didn’t intrude on the sound tutorial The idea, however, is good You could use the Graphics class

to draw additional interface artwork, for example, and still keep the file size low.

Trang 8

The createButton() function in lines 79 through 87 instantiates a button,

positions it on the stage, adds a mouse click event listener, and adds the but-ton to the display list This later lets us create butbut-tons with only one line of code, as seen with the first button in line 89 With three or more buttons, this approach can really be economical

The function takes three arguments: the y coordinate to place the button

on the stage, the label for the button, and the function that will be triggered when the user clicks on the button Although this book has shown how to pass numbers and strings into functions, this is the first time we’ve used a function as an argument This is a handy process that’s not only expedient, but also emphasizes the fact that functions are objects too, just like numbers and strings

As mentioned, line 89 creates the first button, passing a y-position of 40, a label of “Play” and the onPlaySound() function, created earlier, as the

func-tion to execute when the button is clicked

76 //playback complete listener function

77 import com.learningactionscript3.ui.RoundRectButton;

78

79 function createButton(yLoc:Number, labl:String,

80 func:Function):void {

81 var btn:RoundRectButton =

82 new RoundRectButton(100,20,10,2,0x000099,labl,0xFFFFFF);

83 btn.x = 20;

84 btn.y = yLoc;

85 btn.addEventListener(MouseEvent.CLICK, func, false, 0, true);

86 addChild(btn);

87 }

88

89 createButton(40, "Play" , onPlaySound);

The remainder of the script is dedicated to the pause and stop buttons Lines

91 through 98 create the pause button, setting its y location to 65 and adding the onPauseSound() function as its mouse click listener In line 93, the

func-tion checks to see whether the sound is playing and, if so, stores the current playback position in the soundPosition variable It then stops the sound and

sets the isPlaying variable to false so the sound can play again later.

Lines 99 through 102 follow the same process but are even simpler The stop button is created in line 99, which places the button below the previously cre-ated play and pause buttons, and adds the onStopSound() method as the

but-ton’s mouse click listener The functionality required by manually stopping the sound is the same as the functionality required when the sound stops on its own in the onPlayComplete() function (lines 67 through 75) Therefore,

all that’s required here is to call that function

However, because onPlayComplete() is a listener function, it expects an

event argument Calling the function without supplying the expected event argument will cause an argument count mismatch error We can get around

Trang 9

Buffering Sounds

this by sending null to the function to stand in for the event The null value

will satisfy the type checking at the listener function because null is the

default value for all events As long as your listener function doesn’t rely on

specific information from the event, such as mouse coordinates or keyboard

key code values, this technique makes it possible to use listener functions not

only when an event occurs, but also manually

90 //playback complete listener function

91 createButton(65, "Pause" , onPauseSound);

92 function onPauseSound(evt:MouseEvent):void {

93 if (isPlaying) {

94 soundPosition = channel.position;

95 channel.stop();

96 isPlaying = false;

97 }

98 }

99 createButton(90, "Stop" , onStopSound);

100 function onStopSound(evt:MouseEvent):void {

101 onPlayComplete(null);

102 }

At this point, you should be able play, pause, and stop your sound, and both

the load and play progress bar should reach 100 pixels in width upon their

respective completions

Buffering Sounds

Waiting to play a sound until it’s fully loaded will prevent errors or stutters

that might otherwise occur during the loading process This method,

howev-er, does suffer from the drawback of having to wait An alternative approach

is to preload only a portion of the sound prior to playback, and then play

the sound while it continues to download progressively to Flash Player in the

background The principle behind this approach is to preload a buffer that

can stay ahead of playback during the time required to download the

remain-der of the sound You’ll still need to wait, but not as much

How much of the sound should you buffer? That depends on how you plan

to distribute your project Theoretically, if you have no load time, you need

no buffer time because the sound loads instantly This is usually true of local

files, when you are not loading the sound from the Internet For remote files,

connection speeds can dictate how much sound needs to be preloaded If you

know you’ll only encounter broadband connection speeds, you can buffer

less of the sound If you’re worried about slower connections, you may want

to buffer more of the sound to prevent the playback from catching up with

the loading process and stalling playback

To specify the buffer time, you must use the SoundLoaderContext class at

the time of sound loading The number of milliseconds of sound to buffer is

passed to the constructor when instantiating the class; otherwise, a default

value of 1000 is used After instantiating the class, you then pass the resulting

N OT E

For more information about listener functions and the argument count mismatch error, see the “Using Event Listeners” section of Chapter 3.

Trang 10

instance into the sound load() method, as a second parameter following the URLRequest object

The following example adapts the start of our audio player by inserting line

2, and modifying line 4 It buffers 5 seconds of the loaded sound before the

play() method will execute This modification can be found in the player_

buffering.fla source file

1 var snd:Sound = new Sound();

2 var context: SoundLoaderContext = new SoundLoaderContext (5000);

3 var req:URLRequest = new URLRequest( "song.mp3" );

4 snd load (req, context);

Changing Sound Volume and Pan

During playback, it’s possible to manipulate the volume and pan of indi-vidual channels, as well as the global mixer containing all sounds Doing so requires the SoundTransform class.

The process involves starting with a SoundTransform instance (either by

creating a new instance or by storing a reference to the existing transform object of the channel or mixer), setting the volume and/or pan setting of that instance, and then applying the transformation to the channel For example, this snippet will set the volume of a SoundChannel instance called channel

to 50 percent

var trans:SoundTransform = new SoundTransform();

trans.volume = 0.5;

channel.soundTransform = trans;

This syntax will set the volume of a channel to half of what it currently is: var trans:SoundTransform = channel.soundTransform;

trans.volume *= 0.5;

channel.soundTransform = trans;

Notice that the first example sets the volume of a new SoundTransform

instance to 0.5, while the second example multiplies the volume of an exist-ing SoundTransform instance by 0.5 The first example will set the volume to

50 percent, regardless of its prior setting, but the second example will cut the current volume in half For example, if the second volume was originally 50 percent, it would then be 25 percent

Most ActionScript 3.0 settings that require percentage values use a unit range

of 0 to 1 For example, volume is expressed as a range of 0 (muted) to 1 (full volume) with any interim value expressed as a percentage of full volume

To determine a value that describes a pan setting between left and right stereo channels, both a percentage left and a percentage right are required Therefore, the units are expressed as a range of –1 (full left) through 0 (cen-tered) to 1 (full right) Negative interim values reflect some degree of pan left,

N OT E

Remember that buffering will have

little effect when testing locally because

the loading process will complete very

quickly You may wish to upload your

test files to a server, and perhaps even

use a very large sound file, to test your

efforts.

Ngày đăng: 06/07/2014, 18:20

TỪ KHÓA LIÊN QUAN

w