TweetFollow Us on Twitter

MACINTOSH C CARBON
MACINTOSH C CARBON: A Hobbyist's Guide To Programming the Macintosh in C
Version 1.0
2001 K. J. Bricknell
Go to Contents Go to Program Listing

CHAPTER 24

SOUND

Introduction to Sound

On the Macintosh, the hardware and software aspects of producing and recording sounds are very tightly integrated.

Audio Hardware and Sound-Related System Software

The audio hardware includes a speaker or speakers, a microphone, and one or more integrated circuits that convert digital data to analog signals and vice versa.

The sound-related system software managers are as follows:

  • The Sound Manager. The Sound Manager provides the ability to:

    • Play sounds through the speaker or speakers.

    • Manipulate sounds, that is, vary such characteristics as loudness, pitch, timbre, and duration.

    • Compress sounds so that they occupy less disk space.

  • The Sound Input Manager. The Sound Input Manager provides the ability to record sounds through a microphone or other sound input device.

  • The Speech Manager. The Speech Manager provides the ability to convert written text into spoken words.

Sound Input and Output Capabilities

The basic audio hardware, together with the sound-related system software, provides for the following capabilities:

  • The playing back of digitally recorded sounds. (Digitally recorded sound is referred to as sampled sound.

  • The playback of simple sequences of notes or of complex waveforms.

  • The recording of sampled sounds.

  • The conversion of text to spoken words.

  • The mixing and synchronisation of multiple channels of sampled sounds.

  • The compression and decompression of sound data.

  • The integration and synchronisation of sound production with the display of video and still images. (For example, the Sound Manager is used by QuickTime to handle all the sound data in a QuickTime movie.)

The basic audio hardware and system software also provide the ability to integrate and synchronise sound production with the display of other types of information, such as video and still images. For example, QuickTime uses the Sound Manager to handle all the sound data in a QuickTime movie.

Basic and Enhanced Sound Capabilities

Users can enhance sound playback and recording quality by substituting better speakers and microphones. Audio capabilities may be further enhanced by adding an expansion card containing very high quality digital signal processing (DSP) circuitry, together with sound input or output hardware. Another enhancement option is to add a MIDI interface to one of the serial ports. Fig 1 illustrates the basic sound capabilities of the Macintosh and how those capabilities may be further enhanced and extended.

Sound Data

The Sound Manager can play sounds defined using one of three kinds of sound data:

  • Square Wave Data. Square-wave data can be used to play a simple sequence of sounds in which each sound is described by frequency (pitch), amplitude (volume), duration.

  • Wave-Table Data. Wave table data may be used to produce more complex sounds than are possible using square-wave data. A wave cycle is represented as an array of bytes that describe the timbre (tone) of a sound at a point in the cycle.

  • Sampled-Sound Data. Sampled sound data is a continuous list of relative voltages over time that allow the Sound Manager to reconstruct an arbitrary analog wave form. They are typically used to play back prerecorded sounds such as speech or special sound effects

This chapter is oriented primarily towards the recording and playback of sampled sounds.

About Sampled Sound

Two basic characteristics affect the quality of sampled sound. Those characteristics are sample rate and sample size.

Sample Rate

Sample rate, or the rate at which voltage samples are taken, determines the highest possible frequency that can be recorded. Specifically, for a given sample rate, sounds can be sampled up to half that frequency. For example, if the sample rate is 22,254 samples per second (that is, 22,254 hertz, or Hz), the highest frequency that can be recorded is about 11,000 Hz. A commercial compact disc is sampled at 44,100 Hz, providing a frequency response of up to about 20,000 Hz, which is the limit of human hearing.

Sample Size

Sample size, or quantisation, determines the dynamic range of the recording (the difference between the quietest and the loudest sound). If the sample size is eight bits, 256 discrete voltage levels can be recorded. This provides approximately 48 decibels (dB) of dynamic range. A compact disc's sample size is 16 bits, which provides about 96 dB of dynamic range. (Humans with good hearing are sensitive to ranges greater than 100 dB.)

Sound Manager Capabilities

The Sound Manager supports 16-bit stereo audio samples with sample rates up to 64kHz.

Storing Sampled Sounds

Sampled-sound data is made up of a series of sample frames. You can use the Sound Manager to store sampled sounds in one of two ways, either in sound resources or in sound files.

Sound Components

The Sound Manager uses sound components to modify sound data. A sound component is a stand-alone code resource that can perform operations on sound data such as compression, decompression, and converting sample rates. Sound components may be hooked together in series to perform complex tasks, as shown in the example at Fig 2.

The Sound Manager is aware of the sound output device selected by the user and assembles a component chain suitable for producing the desired quality of sound on that device. Thus your application is generally unaware of the sound component chain assembled to produce a sound on the selected output device.

Compression/Decompression Components

Components which compress and decompress sound are called codecs (compression/decompression components). Apple Computer supplies codecs that can handle 3:1 and 6:1 compression and expansion, which are suitable for most audio requirements. The Sound Manager can use any available codec to handle compression and expansion of audio data.

A term closely associated with the subject of codecs is MACE (Macintosh Audio Compression and Expansion). MACE is a collection of Sound Manager functions which provide audio data compression and expansion capabilities in ratios of either 3:1 or 6:1. The Sound Manager uses codecs to handle the MACE capabilities.

Sound Resources

A sound resource is a resource of type 'snd ' that contains sound commands (see below) and possibly also sound data. Sound resources provide a simple way for you to incorporate sounds into your application.

Sound Production

Sound Channels

A Macintosh produces sound when the Sound Manager sends data through a sound channel to the audio hardware. A sound channel is basically a queue of sound commands (see below), which might be placed into the sound channel by your application or by the Sound Manager itself.

The Sound Manager uses the SndChannel data type to define a sound channel:

     struct SndChannel 
     {
       SndChannelPtr   nextChan;       // Pointer to next channel.
       Ptr             firstMod;       // (Used internally.)
       SndCallBackUPP  callBack;       // Pointer to callback function.
       long            userInfo;       // Free for application's use.
       long            wait;           // (Used internally.)
       SndCommand      cmdInProgress;  // (Used internally.)
       short           flags;          // (Used internally.)
       short           qLength;        // (Used internally.)
       short           qHead;          // (Used internally.)
       short           qTail;          // (Used internally.)
       SndCommand      queue[128];     // (Used internally.)
     }

     typedef struct SndChannel SndChannel;
     typedef SndChannel *SndChannelPtr;

Multiple Sound Channels

It is possible to have several channels of sound open at one time. The Sound Manager (using the Apple Mixer sound component) mixes together the data coming from all open sound channels and sends a single stream of sound data to the current sound output device. This allows a single application to play two or more sounds at once. It also allows multiple applications to play sounds at the same time.

Sound Commands

When you call the appropriate Sound Manager function to play a sound, the Sound Manager issues one or more sound commands to the audio hardware. A sound command is an instruction to produce sound, modify sound, or otherwise contribute to the overall process of sound production. The structure of a sound command is defined by the SndCommand data type:

     struct SndCommand 
     {
       unsigned short  cmd;     // Command number.
       short           param1;  // First parameter.
       long            param2;  // Second parameter.
     };

     typedef struct SndCommand SndCommand;

The Sound Manager provides a rich set of sound commands, which are defined by constants. Some examples are as follows:

     quietCmd  = 3   Stop the sound currently playing.
     flushCmd  = 4   Remove all commands currently queued in specified sound channel.
     syncCmd   = 14  Synchronise multiple channels of sound.
     soundCmd  = 80  Install a sampled sound as a voice in a channel.
     bufferCmd = 81  Play a buffer of sampled-sound data. 

Several Sound Manager sound commands are not available in Carbon.

Sound Commands In 'snd ' Resources

A simple way to issue sound commands is to call the function SndPlay, specifying a sound resource of type 'snd ' that contains the sound commands you want to issue.

Often, a 'snd ' resource consists only of a single sound command (usually the bufferCmd command) together with data that describes a sampled sound to be played. The following is an example of such a 'snd ' resource, shown in the form of the output of the MPW tool DeRez when applied to the resource:

     data 'snd ' (19068,"My sound",purgeable) 
     {
       /* Sound resource header */
         $"0001"      /* Format type. */
         $"0001"      /* Number of data types. */
         $"0005"      /* Sampled-sound data. */
         $"00000080"  /* Initialisation option: initMono. */
       /* Sound commands */
         $"0001"      /* Number of sound commands that follow (1). */
         $"8051"      /* Command 1 (bufferCmd). */
         $"0000"      /* param1 = 0. */
         $"00000014"  /* param2 = offset to sound header (20 bytes). */
       /* Sampled sound header (Standard sound header)*/
         $"00000000"  /* samplePtr  Pointer to data (it follows immediately). */
         $"00000BB8"  /* length  Number of bytes in sample (3000 bytes). */
         $"56EE8BA3"  /* sampleRate  Sampling rate of this sound (22 kHz). */
         $"000007D0"  /* loopStart  Starting of the sample's loop point. */
         $"00000898"  /* loopEnd  Ending of the sample's loop point. */
         $"00"        /* encode  Standard sample encoding. */
         $"3C"        /* baseFrequency  BaseFrequency at which sample was taken. */
                      /* sampleArea[]  Sampled sound data */
         $"80 80 81 81 81 81 81 81 80 80 80 80 80 81 82 82"
         $"82 83 82 82 81 80 80 7F 7F 7F 7E 7D 7D 7D 7C 7C"
         (Rest of sampled sound data.)
     };

Note that the sound resource header section indicates that the sound is defined using sampled-sound data. Note also that the sound commands section contains a call to a single sound command (the bufferCmd command (0x51)) and that the offset bit of the command number is set to indicate that the sound data is contained within the resource itself. (Data can also be stored in a buffer separate from a sound resource.) The second parameter to the bufferCmd command indicates the offset from the beginning of the resource to the sampled sound header, which immediately follows the sound commands section.

The sampled sound header shown is a standard sound header, which can reference only buffers of monophonic 8-bit sound. The extended sound header is used for 8-bit or 16-bit stereo sound data as well as monophonic sound data. The compressed sound header is used to describe compressed sound data, whether monophonic or stereo.

Note that the first part of the sampled sound header contains information about the sample and that the sampled sound data is itself part of the sampled sound header.

Sending Sound Commands Directly From the Application

You can also send sound commands one at a time into a sound channel by repeatedly calling the SndDoCommand function. The commands are held in a queue and processed in a first-in, first-out order. Alternatively, you can bypass a sound queue altogether by calling the SndDoImmediate function

Synchronous and Asynchronous Sound

You can play sounds either synchronously or asynchronously. When your application plays a sound synchronously, it cannot continue executing until the sound has finished playing. When your application plays a sound asynchronously, it can continue other processing while the sound is playing.

From a programming standpoint, asynchronous sound production is considerably more complex than synchronous sound production.

Playing a Sound

Playing a Sound Resource

The Sound Manager function SndStartFilePlay (starts a file playing from disk), together with the associated functions SndPauseFilePlay, SndStopFilePlay, SndPlayDoubleBuffer, are not available in Carbon.

You can load a sound resource into memory and then play it using the SndPlay function. As previously stated, a 'snd ' resource contains sound commands that play the desired sound and might also contain sound data. If the sound data is compressed, SndPlay decompresses the data in order to play the sound.

Channel Allocation

If you pass NULL in the first parameter of SndPlay, a sound channel will be automatically allocated to play the sound and then automatically disposed of when the sound has finished playing.

Playing Sounds Asynchronously

The Sound Manager allows you to play sounds asynchronously only if you allocate sound channels yourself. If you use such a technique, your application will need to dispose of a sound channel whenever the application finishes playing a sound. In addition, your application might need to release a sound resource that you played on a sound channel.

The Sound Manager provides certain mechanisms that allow your application to ascertain when a sound finishes playing, so that it can arrange to dispose of, firstly, a sound channel no longer being used and, secondly, other data (such as a sound resource) that you no longer need after disposing of the channel. Despite the existence of these mechanisms, the programming aspects of asynchronous sound remain rather complex. For that reason, the demonstration program files associated with this chapter include a library, called AsynchSoundLib (AsynchSoundLib68K for the 680x0 version or AsynchSoundLibPPC for thePowerPC version), which support asynchronous sound playback and which eliminates the necessity for your application to itself include source code relating to the more complex aspects of asynchronous sound management.

AsynchSoundLib, which may be used by any application that requires a straightforward and uncomplicated interface for asynchronous sound playback, is documented following the Constants, Data Types, and Functions section of this chapter.

Sound Recording - Mac OS 8/9

On Mac OS 8/9, the Sound Input Manager provides a high-level function that allow your application to record sounds from the user and store them in memory. When you call this functions, the Sound Input Manager presents the sound recording dialog shown at Fig 3.

The Sound Manager function SndRecordToFile (records sound data to a file) is not available in Carbon.

Recording a Sound Resource

You can record sounds from the current input device using the SndRecord function. When calling SndRecord, you can pass a handle to a block of memory in the fourth parameter. The incoming data will then be stored in that block, the size of which determines the recording time available. If you pass NULL in the fourth parameter, the Sound Input Manager allocates the largest possible block in the application heap. Either way, the Sound Input Manager resizes the block when the user clicks the Save button.

When you have recorded a sound, you can play it back by calling SndPlay and passing it the handle to the block of memory in which the sound data is stored. That block has the structure of a 'snd ' resource, but its handle is not a handle to an existing resource. To save the recorded data as a resource, you can use the appropriate Resource Manager functions in the usual way.

Recording Quality

One of the following constants should be passed in the third parameter of the SndRecord call so as to specify the recording quality required:

Constant

Value

Meaning

siCDQuality 'cd '

44.1kHz, stereo, 16 bit.

siBestQuality 'best'

22kHz, mono, 8 bit.

siBetterQuality 'betr'

22kHz, mono, 3:1 compression.

siGoodQuality 'good'

22KHz, mono, 6:1 compression

The highest quality sound naturally requires the greatest storage space. Accordingly, be aware that, for most voice recording, you should specify siGoodQuality.

As an example of the storage space required for sounds, one minute of monophonic sound recorded with the same fidelity as a commercial compact disc occupies about 5.3 MB of disk space, and one minute of telephone-quality speech takes up more than half a megabyte.

Speech

The Speech Manager converts text into sound data, which it passes to the Sound Manager to play through the current sound output device. The Speech Manager's interaction with the Sound Manager is transparent to your application, so you do not need to be familiar with the Sound Manager to take advantage of the Speech Manager's capabilities.

Your application can initiate speech generation by passing a string or a buffer of text to the Speech Manager. The Speech Manager is responsible for sending the text to a speech synthesiser, which can include one or more voices, each of which may have different tonal qualities.

Generating Speech From a String

The SpeakString function is used to convert a text string into speech. SpeakString automatically allocates a speech channel, produces the speech on that channel, and then disposes of the speech channel.

Asynchronous Speech

Speech generation is asynchronous, that is, control returns to your application before SpeakString finishes speaking the string. However, because SpeakString copies the string you pass it into an internal buffer, you are free to release the memory you allocated for the string as soon as SpeakString returns.

Synchronous Speech

If you wish to generate speech synchronously, you can use SpeakString in conjunction with the SpeechBusy function, which returns the number of active speech channels, including the speech channel created by the SpeakString function.

Relevant Constants, Data Types, and Functions

Constants

Recording Qualities

siCDQuality      = 'cd  '   44.1kHz, stereo, 16 bit.
siBestQuality    = 'best'   22kHz, mono, 8 bit.
siBetterQuality  = 'betr'   22kHz, mono, MACE 3:1.
siGoodQuality    = 'good'   22kHz, mono, MACE 6:1.

Typical Sound Commands

quietCmd        = 3   Stop the sound currently playing.
flushCmd        = 4   Remove all commands currently queued in specified sound channel.
syncCmd         = 14  Synchronise multiple channels of sound.
soundCmd        = 80  Install a sampled sound as a voice in a channel.
bufferCmd       = 81  Play a buffer of sampled-sound data. 

Data Types

Sound Channel Structure

struct SndChannel 
{
  SndChannelPtr   nextChan;       // Pointer to next channel.
  Ptr             firstMod;       // (Used internally.)
  SndCallBackUPP  callBack;       // Pointer to callback function.
  long            userInfo;       // Free for application's use.
  long            wait;           // (Used internally.)
  SndCommand      cmdInProgress;  // (Used internally.)
  short           flags;          // (Used internally.)
  short           qLength;        // (Used internally.)
  short           qHead;          // (Used internally.)
  short           qTail;          // (Used internally.)
  SndCommand      queue[128];     // (Used internally.)
}
typedef struct SndChannel SndChannel;
typedef SndChannel *SndChannelPtr;

Sound Command Structure

struct SndCommand 
{
  unsigned short  cmd;  // Command number.
  short    param1;      // First parameter.
  long     param2;      // Second parameter.
};
typedef struct SndCommand SndCommand;

Functions

Playing Sound Resources

void   SysBeep(short duration);
OSErr  SndPlay(SndChannelPtr chan,SndListHandle sndHdl,Boolean async);

Allocating and Releasing Sound Channels

OSErr  SndNewChannel(SndChannelPtr *chan,short synth,long init,SndCallBackUPP userRoutine);
OSErr  SndDisposeChannel(SndChannelPtr chan,Boolean quietNow);

Sending Commands to a Sound Channel

OSErr  SndDoCommand(SndChannelPtr chan,const SndCommand *cmd,Boolean noWait);
OSErr  SndDoImmediate(SndChannelPtr chan,const SndCommand *cmd);

Recording Sounds

OSErr  SndRecord(ModalFilterUPP filterProc,Point corner,OSType quality,
       SndListHandle *sndHandle);

Generating Speech

OSErr  SpeakString(ConstStr255Param textToBeSpoken);
short  SpeechBusy(void);

The AsynchSoundLib Library

The AsynchSoundLib library is intended to provide a straightforward and uncomplicated interface for asynchronous sound playback.

AsynchSoundLib requires that you include a global "attention" flag in your application. At startup, your application must call AsynchSoundLib's initialisation function and provide the address of this attention flag. Thereafter, the application must continually check the attention flag within its main event loop.

AsynchSoundLib's main function is to spawn asynchronous sound tasks, and communication between your application and AsynchSoundLib is carried out on an as-required basis. The basic phases of communication for a typical sound playback sequence are as follows.

  • Your application tells AsynchSoundLib to play some sound.

  • AsynchSoundLib uses the Sound Manager to allocate a sound channel and begins asynchronous playback of your sound.

  • The application continues executing, with the sound playing asynchronously in the background.

  • The sound completes playback. AsynchSoundLib has set up a sound command that causes it (AsynchSoundLib) to be informed immediately upon completion of playback. When playback ceases, AsynchSoundLib sets the application's global attention flag.

  • The next time through your application's event loop, the application notices that the attention flag is set and calls AsynchSoundLib to free up the sound channel.

When your application terminates, it must call AsynchSoundLib to stop any asynchronous playback in progress at the time.

AsynchSoundLib's method of communication with the application minimises processing overhead. By using the attention flag scheme, your application calls AsynchSoundLib's cleanup function only when it is really necessary.

AsynchSoundLib Functions

The following documents those AsynchSoundLib functions that may be called from an application.

To facilitate an understanding of the following, it is necessary to be aware that AsynchSoundLib associates a data structure, referred to in the following as an ASStructure, with each channel. Each ASStructure includes the following fields:

     SndChannel channel;      // The sound channel.
     SInt32     refNum;       // Reference number.
     Handle     sound;        // The sound.
     char       handleState;  // State to which to restore the sound handle.
     Boolean    inUse;        // Is this ASStructure currently in use?

OSErr  AS_Initialise (attnFlag,numChannels);

Boolean  *attnFlag;    Pointer to application's "attention" flag global variable.
SInt16   numChannels;  Number of channels required to be open simultaneously.  If 0 is
                       specified, numChannels defaults to 4.

Returns:  0  No errors.
          Non-zero results of MemError call.

This function stores the address of the application's "attention" flag global variable and then allocates memory for a number of ASStructures equal to the requested number of sound channels.


OSErr  AS_PlayID (resID,refNum);

SInt16  resID    Resource ID of the 'snd ' resource.
SInt32  *refNum  A pointer to a reference number storage variable.  Optional.

Returns:  0  No errors.
          1  No channels available.
          Non-zero results of ResError call.
          Non-zero results of SndNewChannel call.
          Non-zero results of SndPlay call.

This function initiates asynchronous playback of the 'snd ' resource with ID resID.

If you pass a pointer to a variable in their refNum parameters, AS_PlayID and its sister function AS_PlayHandle (see below) return a reference number in that parameter. As will be seen, this reference number may be used to gain more control over the playback process. However, if you simply want to trigger a sound and let it to run to completion, with no further control over the playback process, you can pass NULL in the refNum parameter. In this case, a reference number will not be returned.

First, AS_PlayID attempts to load the specified 'snd ' resource. If successful, the handle state is saved for later restoration, and the handle is made unpurgeable. The function then gets a reference number and a pointer to the next free ASStructure. A sound channel is then allocated via a call to SndNewChannel and the associated ASStructure is initialised. HLockHi is then called to move the sound handle high in the heap and lock it. SndPlay is then called to start the sound playing, playing, the channel.userInfo field is set to indicate that the sound is playing, and a callback function is queued so that AsynchSoundLib will know when the sound has stopped playing. If all this is successful, AS_PlayID returns the reference number associated with the channel (if the caller wants it).


OSErr  AS_PlayHandle(sound,refNum);

Handle  sound    A handle to the sound to be played.
SInt32  *refNum  A pointer to a reference number storage variable.  Optional.

Returns:  0  If no errors.
          1  No channels available.
          Non-zero results of SndNewChannel call.
          Non-zero results of SndPlay call.

This function initiates asynchronous playback of the sound referred to by sound.

The AS_PlayHandle function is similar to AS_PlayID, except that it supports a special case: You can pass AS_PlayHandle a NULL handle. This causes AS_PlayHandle to open a sound channel but not call SndPlay. Normally, you do this when you want to get a sound channel and then send sound commands directly to that channel yourself. (See AS_GetChannel, below.)

If a handle is provided, its current state is saved for later restoration before it is made unpurgeable. AS_PlayHandle then gets a reference number and a pointer to a free ASStructure. A sound channel is then allocated via a call to SndNewChannel and the associated ASStructure is initialised. Then, if a handle was provided, HLockHi is called to move the sound handle high in the heap and lock it, following which SndPlay is called to start the sound playing, the channel.userInfo field is set to indicate that the sound is playing, and a callback function is queued so that AsynchSoundLib will know when the sound has stopped playing. Finally, the reference number associated with the channel is returned (if the caller wants it).


OSErr  AS_GetChannel(refNum,channel);

Sint32         refNum    Reference number.
SndChannelPtr  *channel  A pointer to a SoundChannelPtr.

Returns:  0  No errors.
          2  If refNum does not refer to any current ASStructure.

This function searches for the ASStructure associated with refNum. If one is found, a pointer to the associated sound channel is retuned in the channel parameter.

AS_GetChannel is provided so as to allow an application to gain access to the sound channel associated with a specified reference number and thus gain the potential for more control over the playback process. It allows an application to use AsynchSoundLib to handle sound channel management while at the same time retaining the ability to send sound commands to the channel. This is most commonly done to play looped continuous music, for which you will need to provide a sound resource with a loop and a sound command to install the music as a voice. First, you open a channel by calling AS_PlayHandle, specifying NULL in the first parameter. (This causes AS_PlayHandle to open a sound channel but not call SndPlay.) Armed with the returned reference number associated with that channel, you then call AS_GetChannel to get the SndChannelPtr, which you then pass as the first parameter in a call to SndPlay. Finally, you send a freqCmd command to the channel to start the music playing. The playback will keep looping until you send a quietCmd command to the channel.


void  AS_CloseChannel(void);

This function is called from the application's event loop if the application's "attention" flag is set. It clears the "attention" flag and then performs playback cleanup by iterating through the ASStructures looking for structures which are both in use (that is, the inUse field contains true) and complete (that is, the channel.userInfo field has been set by AsyncSoundLib's callback function to indicate that the sound has stopped playing). It frees up such structures for later use and closes the associated sound channel.


void  AS_CloseDown(void);

AS_CloseDown checks that AsynchSoundLib was previously initialised, stops all current playback, calls AS_CloseChannel to close open sound channels, and disposes of the associated ASStructures.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

The beginner's guide to Warbits
Warbits is a turn-based strategy that's clearly inspired by Nintendo's Advance Wars series. Since turn-based strategy games can be kind of tricky to dive into, see below for a few tips to help you in the beginning. Positioning is crucial [Read... | Read more »
How to upgrade your character in Spellsp...
So you’ve mastered the basics of Spellspire. By which I mean you’ve realised it’s all about spelling things in a spire. What next? Well you’re going to need to figure out how to toughen up your character. It’s all well and good being able to spell... | Read more »
5 slither.io mash-ups we'd love to...
If there's one thing that slither.io has proved, it's that the addictive gameplay of Agar.io can be transplanted onto basically anything and it will still be good fun. It wouldn't be surprising if we saw other developers jumping on the bandwagon,... | Read more »
How to navigate the terrain in Sky Charm...
Sky Charms is a whimsical match-'em up adventure that uses creative level design to really ramp up the difficulty. [Read more] | Read more »
Victorious Knight (Games)
Victorious Knight 1.3 Device: iOS Universal Category: Games Price: $1.99, Version: 1.3 (iTunes) Description: New challenges awaits you! Experience fresh RPG experience with a unique combat mechanic, packed with high quality 3D... | Read more »
Agent Gumball - Roguelike Spy Game (Gam...
Agent Gumball - Roguelike Spy Game 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Someone’s been spying on Gumball. What the what?! Two can play at that game! GO UNDERCOVERSneak past enemy... | Read more »
Runaway Toad (Games)
Runaway Toad 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: It ain’t easy bein’ green! Tap, hold, and swipe to help Toad hop to safety in this gorgeous new action game from the creators of... | Read more »
PsyCard (Games)
PsyCard 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: From the makers och Card City Nights, Progress To 100 and Ittle Dew PSYCARD is a minesweeper-like game set in a cozy cyberpunk... | Read more »
Sago Mini Robot Party (Education)
Sago Mini Robot Party 1.0 Device: iOS Universal Category: Education Price: $2.99, Version: 1.0 (iTunes) Description: -- Children's Technology Review Editor's Choice -- | Read more »
Egz – The Origin of the Universe (Games...
Egz – The Origin of the Universe 1.0.2 Device: iOS Universal Category: Games Price: $3.99, Version: 1.0.2 (iTunes) Description: ►►► Special offer until 2nd may : get the game at 2.99€ instead of 3.99€ ! ◄◄◄ Egz is a mesmerizing mix... | Read more »

Price Scanner via MacPrices.net

Mac minis on sale for up to $100 off MSRP
B&H Photo has Mac minis on sale for up to $100 off MSRP including free shipping plus NY sales tax only: - 1.4GHz Mac mini: $449 $50 off MSRP - 2.6GHz Mac mini: $649 $50 off MSRP - 2.8GHz Mac mini... Read more
13-inch Retina MacBook Pros on sale for up to...
B&H Photo has 13″ Retina MacBook Pros on sale for $130-$200 off MSRP. Shipping is free, and B&H charges NY tax only: - 13″ 2.7GHz/128GB Retina MacBook Pro: $1169 $130 off MSRP - 13″ 2.7GHz/... Read more
Apple price trackers, updated continuously
Scan our Apple Price Trackers for the latest information on sales, bundles, and availability on systems from Apple’s authorized internet/catalog resellers. We update the trackers continuously: - 15″... Read more
SanDisk Half-Terabyte SSD Optimized for Every...
SanDisk Corporation has announced the SanDisk Z410 SSD, a cost-competitive, half-terabyte solid state drive (SSD) that enables manufacturers to design for a broad range of desktop PCs and laptops.... Read more
Churchill Downs Racetrack Selects VenueNext t...
Churchill Downs Racetrack has announced an agreement with VenueNext to implement its technology platform for the start of Churchill Downs 2016 Spring Meet, which includes the 142nd running of the... Read more
Record 700 Million Pounds of CE Recycled in 2...
The Consumer Technology Association (CTA) reports that a record-setting 700 million pounds of consumer electronics (CE) have been recycled under the eCycling Leadership Initiative (ELI). According to... Read more
Price drops on clearance 12-inch Retina MacBo...
B&H Photo has dropped prices on leftover 2015 12″ Retina MacBooks with models now available starting at $999. Shipping is free, and B&H charges NY tax only: - 12″ 1.1GHz Gray Retina MacBook... Read more
15-inch Retina MacBook Pros available for $20...
B&H Photo has 15″ Retina MacBook Pros on sale for up to $210 off MSRP. Shipping is free, and B&H charges NY tax only: - 15″ 2.2GHz Retina MacBook Pro: $1799 $200 off MSRP - 15″ 2.5GHz Retina... Read more
Target offers Apple Watch Sport for $50 off M...
Target has Apple Watch Sports on sale for $50 off MSRP for a limited time. Choose free shipping or free local store pickup (if available). Sale prices for online orders only, in-store prices may vary... Read more
Apple restocks Certified Refurbished Mac mini...
Apple has restocked Certified Refurbished 2014 Mac minis, with models available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: - 1.4GHz Mac mini: $419 $... Read more

Jobs Board

*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
Restaurant Manager (Neighborhood Captain) - A...
…in every aspect of daily operation. WHY YOU'LL LIKE IT: You'll be the Big Apple . You'll solve problems. You'll get to show your ability to handle the stress and Read more
Simply Mac *Apple* Specialist- Service Repa...
Simply Mac is the largest premier retailer of Apple products in the nation. In order to support our growing customer base, we are currently looking for a driven Read more
*Apple* Retail - Multiple Positions - Apple,...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.