Skip to content Skip to navigation Skip to collection information

OpenStax_CNX

You are here: Home » Content » Object-Oriented Programming (OOP) with ActionScript » Sound in ActionScript

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Sound in ActionScript

Module by: R.G. (Dick) Baldwin. E-mail the author

Summary: Learn to play sounds in ActionScript, both continuously and on call. Also learn how handle events fired by SoundChannel objects.

Note:

Click Sound03 to run the ActionScript program from this lesson. (Click the "Back" button in your browser to return to this page.)

Preface

General

This tutorial lesson is part of a series of lessons dedicated to object-oriented programming (OOP) with ActionScript.

Note:

All references to ActionScript in this lesson are references to version 3.0 or later.

Several ways to create and launch ActionScript programs

There are several ways to create and launch programs written in the ActionScript programming language. Many of the lessons in this series will use Adobe Flex as the launch pad for the sample ActionScript programs.

An earlier lesson titled The Default Application Container provided information on how to get started programming with Adobe's Flex Builder 3. The lesson titled Using Flex 3 in a Flex 4 World was added later to accommodate the release of Flash Builder 4. (See Baldwin's Flex programming website .) You should study those lessons before embarking on the lessons in this series.

Some understanding of Flex MXML will be required

I also recommend that you study all of the lessons on Baldwin's Flex programming website in parallel with your study of these ActionScript lessons. Eventually you will probably need to understand both ActionScript and Flex and the relationships that exist between them in order to become a successful ActionScript programmer.

Will emphasize ActionScript code

It is often possible to use either ActionScript code or Flex MXML code to achieve the same result. Insofar as this series of lessons is concerned, the emphasis will be on ActionScript code even in those cases where Flex MXML code may be a suitable alternative.

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Supplemental material

I recommend that you also study the other lessons in my extensive collection of online programming tutorials. You will find a consolidated index at www.DickBaldwin.com .

General background information

A sound in ActionScript is represented by an object of the class named Sound .

When the information encapsulated in a Sound object is played , that process is represented by an object of the class named SoundChannel .

According to the documentation :

"The Sound class lets you work with sound in an application. The Sound class lets you create a new Sound object, load and play an external MP3 file into that object, close the sound stream, and access data about the sound, such as information about the number of bytes in the stream and ID3 metadata. More detailed control of the sound is performed through the sound source -- the SoundChannel or Microphone object for the sound -- and through the properties in the SoundTransform class that control the output of the sound to the computer's speakers."

The program that I will explain in this lesson makes use of events and methods of the Sound class and the SoundChannel class.

You will find a lot of interesting and useful information in the document titled Basics of working with sound on the Adobe website, including the following:

"Although there are various sound file formats used to encode digital audio, ActionScript 3.0 and Flash Player support sound files that are stored in the mp3 format. They cannot directly load or play sound files in other formats like WAV or AIFF."

A variety of different sound file converter programs are available on the web that can be used to convert other sound file formats into mp3 format.

Preview

Run the ActionScript program named Sound03

If you have the Flash Player plug-in (version 10 or later) installed in your browser, click here to run the program named Sound03 .

If you don't have the proper Flash Player installed, you should be notified of that fact and given an opportunity to download and install the Flash Player plug-in program.

Demonstrates the use of sound with ActionScript

This project is intended to demonstrate the use of sound with ActionScript. It also displays the image of a cloudy sky shown in Figure 1, but the only purpose of the image is to make it obvious when the program starts running.

Figure 1: Sound03 image.
Sound03 image.
Missing image

Stormy weather

The project is designed to give you the impression of the sounds that you might hear while sitting on your covered deck looking at the sky during a thunder storm.

Four stormy-weather sounds

The project plays the following sounds extracted from mp3 files:

  • rain
  • wind
  • sizzle
  • thunder

The rain sound is continuous.

The wind sound is played on startup and then occasionally thereafter on the basis of a random number generator.

The sizzle sound is also played occasionally on the basis of a random number generator. (You will probably need to be patient to hear this sound because it isn't played very often.) As soon as the sizzle sound finishes, the sound of a thunder clap is played.

Discussion and sample code

Note:

If you develop this project using FlashDevelop , you will need to manually copy all of the sound files into the bin folder.

The project file structure

The final project file structure, captured from the FlashDevelop project window, is shown in Figure 2.

Figure 2: Project file structure for Sound03.
Project file structure for Sound03.
Missing image

As you can see in Figure 2, all of the sound and image files are stored in the folder named src . In addition, all of the sound files were manually copied into the folder named bin .

Will explain in fragments

I will explain the code for this program in fragments. Complete listings of the MXML code and the ActionScript code are provided in Listing 10 and Listing 11 near the end of the lesson.

The MXML code

The MXML code is shown in Listing 1 and also in Listing 10 for your convenience.

Listing 1: MXML code for the project named Sound03.

<?xml version="1.0" encoding="utf-8"?>
<!--
This project is intended to demonstrate the use of sound 
with ActionScript. See the file named Driver.as for more
information
-->

<mx:Application 
  xmlns:mx="http://www.adobe.com/2006/mxml" 
  xmlns:cc="CustomClasses.*">
  
  <cc:Driver/>

</mx:Application>

As is often the case in this series of tutorial lessons, the MXML file is very simple because the program was coded almost entirely in ActionScript. The MXML code simply instantiates an object of the Driver class. From that point forward, the behavior of the program is controlled by ActionScript code.

The ActionScript code

Import directives for the Driver class

The code for the Driver class begins in Listing 2, which shows the package declaration and the import directives.

Listing 2: Import directives for the Driver class

package CustomClasses{
  import flash.display.Bitmap;
  import mx.containers.Canvas;
  import mx.controls.Image;
  import mx.events.FlexEvent;
  import flash.events.TimerEvent;
  import flash.utils.Timer;
  import flash.media.Sound;
  import flash.net.URLRequest;
  import flash.media.SoundChannel;
  import flash.events.Event;

New to this lesson

The directives to import the Sound class, the URLRequest class, the SoundChannel class, and possibly the Event class are all new to this lesson.

Beginning of the Driver class proper

The definition of the Driver class begins in Listing 3.

Listing 3: Beginning of the Driver class proper.

  public class Driver extends Canvas {
    //Extending Canvas makes it possible to locate
    // images with absolute coordinates. The default
    // location is 0,0;
    
    private var smallSky:Image = new Image();    

    //Instantiate a Timer object that will fire ten events
    // per second.
    private var timer:Timer = new Timer(100);
    
    //Declare a counter that will keep track of the number
    // of timer events that have been fired.
    private var loopCntr:uint;
    
    //Declare variables for the four sounds.
    private var sizzle:Sound;
    private var thunder:Sound;
    private var wind:Sound;
    private var rain:Sound;
    
    //Declare variables that are used to control when the
    // thunder sound is played.
    private var channel:SoundChannel;
    private var sizzlePlaying:Boolean = false;

Nothing new here

There is nothing new in Listing 3. I will call your attention to the declaration of variables of type Sound and SoundChannel . Otherwise, no explanation beyond the embedded comments should be required.

The constructor for the Driver class

The constructor for the Driver class is shown in its entirety in Listing 4.

Listing 4: The constructor for the Driver class.

    public function Driver(){//constructor
      //Load the sky image.
      //Note the use of a / to eliminate the "Unable to 
      // resolve asset for transcoding" Compiler Error
      [Embed("/smallsky.jpg")]
      var imgSmall:Class;
      smallSky.load(imgSmall);
      
      //Load four sound files and play two of them now.
      sizzle = new Sound();
      sizzle.load(new URLRequest("sizzle.mp3"));
      
      thunder = new Sound();
      thunder.load(new URLRequest("thunder.mp3"));
      
      wind = new Sound();
      wind.load(new URLRequest("wind.mp3"));
      //Play the wind sound through twice at startup.
      wind.play(0,2);
      
      rain = new Sound();
      rain.load(new URLRequest("rain.mp3"));
      //Play the rain sound forever
      rain.play(0,int.MAX_VALUE);   
      
      //Register an event listener on the CREATION_
      // COMPLETE event.
      this.addEventListener(FlexEvent.CREATION_COMPLETE,
                                 creationCompleteHandler);
    } //end constructor

There are quite a few things in Listing 4 that are new to this lesson.

Embed the image file

Although the code required to embed the image file in the swf file is not new to this lesson, it is worth highlighting the need to include the slash character to make the code compatible with the FlashDevelop IDE.

Load the sizzle sound

Listing 4 instantiates a new Sound object and stores the object's reference in the instance variable named sizzle . Then it calls the load method on that object to load the contents of the sound file named sizzle.mp3 into the new Sound object.

The load method of the Sound class

Here is part of what the documentation has to say about the load method of the class named Sound :

"Initiates loading of an external MP3 file from the specified URL. If you provide a valid URLRequest object to the Sound constructor, the constructor calls Sound.load() for you. You only need to call Sound.load() yourself if you don't pass a valid URLRequest object to the Sound constructor or you pass a null value.
Once load() is called on a Sound object, you can't later load a different sound file into that Sound object. To load a different sound file, create a new Sound object."

Because I didn't provide a URLRequest object to the constructor when I instantiated the object of the Sound class, it was necessary for me to call the load method on the Sound object to load the sound file named sizzle.mp3 .

Required parameter for the load method

Only one parameter is required by the load method and it must be of type URLRequest . To make a long story short, at least for the case where the sound file is located in the src folder as shown in Figure 2, you can create the required URLRequest object by calling the constructor for the URLRequest class and passing the name of the sound file as a String parameter to the constructor as shown in Listing 4.

Don't play the sizzle sound yet

The sizzle sound and the thunder sound are both encapsulated in Sound objects by the constructor in Listing 4. However, those sounds are not played by the constructor.

Encapsulate and play the wind wound

Listing 4 uses similar code to encapsulate the contents of the file named wind.mp3 in an object of type Sound referred to by the instance variable named wind .

Then Listing 4 calls the play method on the wind object to cause the wind sound to be played from beginning to end twice when the program first starts running. (It will be played again later at random times.)

The play method of the Sound class

Here is part of what the documentation has to say about the play method of the Sound class:

"Generates a new SoundChannel object to play back the sound. This method returns a SoundChannel object, which you access to stop the sound and to monitor volume. (To control the volume, panning, and balance, access the SoundTransform object assigned to the sound channel.) "

In other words, the play method causes the sound to start playing through a SoundChannel object, which you can manipulate to achieve various effects.

Didn't save a reference to SoundChannel object

Because I didn't have any need to manipulate the wind sound by way of the SoundChannel object, I didn't capture and save a reference to the object returned by the play method.

Parameters of the play method of the Sound class

The play method has three parameters, each of which has a default value. By default (and this doesn't seem to agree with the documentation) , if you call the play method on a Sound object and don't pass any parameters, the sound encapsulated in the object will be played once, starting at the beginning of the sound.

The first parameter

The first parameter is the initial position in milliseconds at which playback should start. The default value for this parameter is 0, which causes the sound to start at the beginning by default.

As is always the case with default parameters, if you want to provide a non-default value for the second parameter, you must also provide a value for the first parameter. When the play method is called on the wind sound in Listing 4, a value of 0 is passed as the first parameter to cause the sound to play from the beginning.

The second parameter

Instead of telling you what the documentation seems to say about the second parameter, I'm going to tell you how the second parameter behaves, which doesn't seem to agree with the documentation.

The value of the second parameter defines the number of times the sound will be played before the sound channel stops playback. For example, a value of 2 is passed as the second parameter when the play method is called on the wind sound in Listing 4. This parameter, in conjunction with the first parameter, causes the wind sound to be played through twice from the beginning to the end when the program starts running.

Rain, rain, go away: not any time soon

The maximum possible integer value is passed as the second parameter when the play method is called on the rain sound in Listing 4. This causes the rain sound to play over and over for a length of time that is probably longer than anyone would want to listen to it.

A CREATION_COMPLETE event listener

The last statement in the constructor in Listing 4 registers a CREATION_COMPLETE event handler on the Canvas object. You are already familiar with event listeners of this type. The code for the listener is shown in its entirety in Listing 5.

Listing 5: A CREATION_COMPLETE event handler.

    private function creationCompleteHandler(
                          event:mx.events.FlexEvent):void{
      
      //Set the width and height of the Canvas object
      // based on the size of the bitmap in the smallSky
      // image.
      this.width = Bitmap(smallSky.content).width;
      this.height = Bitmap(smallSky.content).height;
      
      //Add the image to this Canvas object.
      this.addChild(smallSky);
      
      //Register a timer listener and start the timer
      // running.
      timer.addEventListener(TimerEvent.TIMER, onTimer);
      timer.start();      

    } //end creationCompleteHandler

As you learned in earlier lessons, this handler method is executed when the Canvas object has been fully created.

Nothing new here

There is nothing new in Listing 5. The code in Listing 5:

  • Sets the width and the height of the Canvas object to match the width and the height of the image that is displayed while the program is running.
  • Adds the image to the Canvas object.
  • Registers an event listener on the Timer object that was instantiated in Listing 3 and starts the timer running to fire ten events per second.

Beginning of the TIMER event handler

The event handler that is registered on the Timer object begins in Listing 6. This method is executed each time the Timer object fires an event.

Listing 6: Beginning of the Timer event handler.

    public function onTimer(event:TimerEvent):void {
      
      //Update the loop counter.
      loopCntr++;
      if (loopCntr == int.MAX_VALUE - 1) {
        //Guard against numeric overflow.
        loopCntr = 0;
      }//end if

Update the loop counter

Among other things, the code in the Timer event handler maintains a count of the number of events that have been fired by the timer. The code in Listing 6 increments the timer each time the event-handler method is executed, and sets the value back to zero when it reaches a very large value to guard against binary overflow.

Play an occasional wind sound

According to the code in Listing 3, the Timer object will fire an event every 100 milliseconds, or ten times per second. That causes the event handler to be called ten times per second.

The code in Listing 7 uses the modulus operator to identify every 25th call to the event handler. This occurs approximately once every 2.5 seconds, depending on the accuracy of the timer.

Listing 7: Play an occasional wind sound.

      if ((loopCntr % 25 == 0) && (Math.random() > 0.75)){
        wind.play();
      }//end if

Let the wind blow: or maybe not

When the code in Listing 7 determines that 2.5 seconds have passed since the last attempt to play the wind sound, it gets a random value of type Number with a value between 0 and 1.0. If that random value is greater than 0.75, it calls the play method on the wind sound to cause the sound to be played once from start to finish.

One wind sound every ten seconds on average

Assuming that the random values are uniformly distributed, about one out of every four random values will be greater than 0.75. Therefore, the wind sound should be played about once every ten seconds on average.

Play an occasional sizzle sound

Listing 8 uses a similar process to play an occasional sizzle sound. Listing 8 also causes the sizzle sound to be followed immediately by a clap of thunder.

Listing 8: Play an occasional sizzle sound.

      if ((loopCntr % 35 == 0) && (Math.random() > 0.5) 
                            && (sizzlePlaying == false)) {
        //Don't play another sizzle sound until this one 
        // finishes.
        sizzlePlaying = true;
        
        //Play the sizzle sound and get a reference to the
        // SoundChannel object through which it is being
        // played.
        channel = sizzle.play();
        
        //Register an event listener that will be called
        // when the sizzle sound finishes playing.
        channel.addEventListener(
              Event.SOUND_COMPLETE, soundCompleteHandler);
      }//end if
      
    }//end onTimer

Save the SoundChannel reference

Listing 8 saves the SoundChannel reference returned by the play method in an instance variable named channel when the play method is called to play the sizzle sound.

Don't corrupt the reference to the SoundChannel object

In order to preclude the possibility of corrupting this reference by changing its value while the sound is playing, Listing 8 uses a Boolean instance variable named sizzlePlaying to guarantee that a new sizzle sound is not played before the previous one finishes.

The value of sizzlePlaying is set to true when the sizzle sound starts playing in Listing 8 and is set to false later when the sizzle sound finishes playing. Because the value of sizzlePlaying is tested by the conditional clause in the if statement in Listing 8, that conditional clause will never return true while sizzlePlaying is true.

Register a SOUND_COMPLETE event handler

The SoundChannel object fires a SOUND_COMPLETE event when the sound that it is playing finishes. Listing 8 registers an event listener on the SoundChannel object that is called each time the sizzle sound finishes playing. As you will see shortly, the code in the event handler sets the value of sizzlePlaying to false and also causes the thunder sound to be played as soon as the sizzle sound finishes.

The SOUND_COMPLETE event handler

The SOUND_COMPLETE event handler is shown in its entirety in Listing 9. This method is called each time the sizzle sound finishes playing.

Listing 9: The SOUND_COMPLETE event handler.

    private function soundCompleteHandler(e:Event):void {
      //Allow another sizzle sound to be played now that 
      // this one is finished.
      sizzlePlaying = false;
      //Play the thunder immediately following the end of
      // the sizzle sound.
      thunder.play();
    }//end soundCompleteHandler
    //--------------------------------------------------//
        
  } //end class
} //end package

Allow another sizzle sound to be played

Listing 9 begins by setting the value of sizzlePlaying to false. This makes it possible for the sizzle sound to be played again when the other two expressions in the conditional clause of the if statement in Listing 8 return true.

Play a thunder clap

Then Listing 9 calls the play method on the thunder sound to cause the thunder sound to be played once immediately following the completion of each sizzle sound.

The end of the program

Listing 9 also signals the end of the Driver class and the end of the program.

Run the program

I encourage you to run this program from the web. Then copy the code from Listing 10 and Listing 11. Use that code to create your own project. Compile and run the project. Experiment with the code, making changes, and observing the results of your changes. Make certain that you can explain why your changes behave as they do.

Resources

I will publish a list containing links to ActionScript resources as a separate document. Search for ActionScript Resources in the Connexions search box.

Complete program listings

Complete listings of the programs discussed in this lesson are provided below.

Listing 10: MXML code for the project named Sound03.

<?xml version="1.0" encoding="utf-8"?>
<!--
This project is intended to demonstrate the use of sound 
with ActionScript. See the file named Driver.as for more
information
-->

<mx:Application 
  xmlns:mx="http://www.adobe.com/2006/mxml" 
  xmlns:cc="CustomClasses.*">
  
  <cc:Driver/>

</mx:Application>

Listing 11: Class named Driver for the project named Sound03.

/*Project Sound03
This project is intended to demonstrate the use of sound 
with ActionScript. It also displays an image of a cloudy 
sky but the only purpose of the image is to make it 
obvious when the program starts running.

This project plays the following sounds extracted from
mp3 files.

rain
wind
sizzle
thunder

The rain sound is continuous.

The wind sound is played occasionally on the basis of a 
random number generator.

The sizzle sound is also played occasionally on the basis
of a random number generator. As soon as the sizzle sound
finishes, a thunder clap sound is played.

Note that with FlashDevelop, you must manually put a copy
of the sound files in the bin folder.
*********************************************************/
package CustomClasses{
  import flash.display.Bitmap;
  import mx.containers.Canvas;
  import mx.controls.Image;
  import mx.events.FlexEvent;
  import flash.events.TimerEvent;
  import flash.utils.Timer;
  import flash.media.Sound;
  import flash.net.URLRequest;
  import flash.media.SoundChannel;
  import flash.events.Event;
  
  //====================================================//
  
  public class Driver extends Canvas {
    //Extending Canvas makes it possible to locate
    // images with absolute coordinates. The default
    // location is 0,0;
    
    private var smallSky:Image = new Image();    

    //Instantiate a Timer object that will fire ten events
    // per second.
    private var timer:Timer = new Timer(100);
    
    //Declare a counter that will keep track of the number
    // of timer events that have been fired.
    private var loopCntr:uint;
    
    //Declare variables for the four sounds.
    private var sizzle:Sound;
    private var thunder:Sound;
    private var wind:Sound;
    private var rain:Sound;
    
    //Declare variables that are used to control when the
    // thunder sound is played.
    private var channel:SoundChannel;
    private var sizzlePlaying:Boolean = false;
    //--------------------------------------------------//
    
    public function Driver(){//constructor
      //Load the sky image.
      //Note the use of a / to eliminate the "Unable to 
      // resolve asset for transcoding" Compiler Error
      [Embed("/smallsky.jpg")]
      var imgSmall:Class;
      smallSky.load(imgSmall);
      
      //Load four sound files and play two of them now.
      sizzle = new Sound();
      sizzle.load(new URLRequest("sizzle.mp3"));
      
      thunder = new Sound();
      thunder.load(new URLRequest("thunder.mp3"));
      
      wind = new Sound();
      wind.load(new URLRequest("wind.mp3"));
      //Play the wind sound through twice at startup.
      wind.play(0,2);
      
      rain = new Sound();
      rain.load(new URLRequest("rain.mp3"));
      //Play the rain sound forever
      rain.play(0,int.MAX_VALUE);   
      
      //Register an event listener on the CREATION_
      // COMPLETE event.
      this.addEventListener(FlexEvent.CREATION_COMPLETE,
                                 creationCompleteHandler);
    } //end constructor
    //--------------------------------------------------//

    //This handler method is executed when the Canvas has
    // been fully created.
    private function creationCompleteHandler(
                          event:mx.events.FlexEvent):void{
      
      //Set the width and height of the Canvas object
      // based on the size of the bitmap in the smallSky
      // image.
      this.width = Bitmap(smallSky.content).width;
      this.height = Bitmap(smallSky.content).height;
      
      //Add the image to this Canvas object.
      this.addChild(smallSky);
      
      //Register a timer listener and start the timer
      // running.
      timer.addEventListener(TimerEvent.TIMER, onTimer);
      timer.start();      

    } //end creationCompleteHandler
    //--------------------------------------------------//
    
    //TimerEvent handler. This method is executed each
    // time the Timer object fires an event.
    public function onTimer(event:TimerEvent):void {
      
      //Update the loop counter.
      loopCntr++;
      if (loopCntr == int.MAX_VALUE - 1) {
        //Guard against numeric overflow.
        loopCntr = 0;
      }//end if
      
      //Play an occasional wind sound.
      if ((loopCntr % 25 == 0) && (Math.random() > 0.75)){
        wind.play();
      }//end if
      
      //Play an occasional sizzle sound followed 
      // immediately by a clap of thunder.
      if ((loopCntr % 35 == 0) && (Math.random() > 0.5) 
                            && (sizzlePlaying == false)) {
        //Don't play another sizzle sound until this one 
        // finishes.
        sizzlePlaying = true;
        //Play the sizzle sound and get a reference to the
        // SoundChannel object through which it is being
        // played.
        channel = sizzle.play();
        //Register an event listener that will be called
        // when the sizzle sound finishes playing.
        channel.addEventListener(
              Event.SOUND_COMPLETE, soundCompleteHandler);
      }//end if
      
    }//end onTimer
    //--------------------------------------------------//
    
    //This method is called each time the sizzle sound
    // finishes playing. Each time it is called, it plays
    // a thunder sound.
    private function soundCompleteHandler(e:Event):void {
      //Allow another sizzle sound to be played now that 
      // this one is finished.
      sizzlePlaying = false;
      //Play the thunder immediately following the end of
      // the sizzle sound.
      thunder.play();
    }//end soundCompleteHandler
    //--------------------------------------------------//
        
  } //end class
} //end package

Miscellaneous

This section contains a variety of miscellaneous materials.

Note:

Housekeeping material
  • Module name: Sound in ActionScript
  • Files:
    • ActionScript00160\ActionScript00160.htm
    • ActionScript00160\Connexions\ActionScriptXhtml00160.htm

Note:

PDF disclaimer: Although the Connexions site makes it possible for you to download a PDF file for this module at no charge, and also makes it possible for you to purchase a pre-printed version of the PDF file, you should be aware that some of the HTML elements in this module may not translate well into PDF.

-end-

Collection Navigation

Content actions

Download:

Collection as:

PDF | EPUB (?)

What is an EPUB file?

EPUB is an electronic book format that can be read on a variety of mobile devices.

Downloading to a reading device

For detailed instructions on how to download this content's EPUB to your specific device, click the "(?)" link.

| More downloads ...

Module as:

PDF | More downloads ...

Add:

Collection to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks

Module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks