Package com.google.gwt.libideas.resources.rg

Source Code of com.google.gwt.libideas.resources.rg.SoundBundleBuilder

/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.libideas.resources.rg;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.libideas.resources.rebind.ResourceContext;
import com.google.gwt.libideas.resources.rebind.ResourceGeneratorUtil;

import com.anotherbigidea.flash.SWFConstants;
import com.anotherbigidea.flash.interfaces.SWFActionBlock;
import com.anotherbigidea.flash.interfaces.SWFActions;
import com.anotherbigidea.flash.interfaces.SWFTags;
import com.anotherbigidea.flash.readers.SWFReader;
import com.anotherbigidea.flash.readers.TagParser;
import com.anotherbigidea.flash.sound.ADPCMHelper;
import com.anotherbigidea.flash.sound.MP3Helper;
import com.anotherbigidea.flash.sound.SoundDefinition;
import com.anotherbigidea.flash.writers.SWFWriter;
import com.anotherbigidea.flash.writers.TagWriter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import javax.sound.sampled.UnsupportedAudioFileException;

/**
* Assimilates sound resources into a flash application.
*/
class SoundBundleBuilder {
  /**
   * Appends sound and export tags for each sample.
   */
  private class Appender extends TagWriter {

    public Appender(SWFTags out) {
      super(out);
    }

    @Override
    public void header(int version, long length, int twipsWidth,
        int twipsHeight, int frameRate, int frameCount) throws IOException {
      // -1 forces the frame count to be recomputed
      super.header(version, length, twipsWidth, twipsHeight, frameRate, -1);
    }

    @Override
    public void tagEnd() throws IOException {
      // Create a sorted array of names by comparing the map entries with the
      // ordered list
      String[] names = new String[sounds.size()];
      for (Map.Entry<String, SoundDefinition> entry : sounds.entrySet()) {
        int i = orderedSounds.indexOf(entry.getValue());
        names[i] = entry.getKey();
      }

      // Place each sound in its own frame.
      for (SoundDefinition def : orderedSounds) {
        int i = orderedSounds.indexOf(def);

        tagDefineSound(i + 100, def.format, def.frequency, def.is16bit,
            def.isStereo, def.sampleCount, def.soundData);

        tagExport(new String[] {names[i]}, new int[] {i + 100});
        tagShowFrame();
      }

      // Prevent the movie from looping
      SWFActions actions = tagDoAction();
      SWFActionBlock block = actions.start(0);
      block.stop();
      block.end();
      actions.done();
      tagShowFrame();

      // End the SWF file
      super.tagEnd();
    }
  }

  private final Map<String, SoundDefinition> sounds = new IdentityHashMap<String, SoundDefinition>();

  private final List<SoundDefinition> orderedSounds = new ArrayList<SoundDefinition>();

  public void assimilate(TreeLogger logger, String name, URL resource)
      throws UnableToCompleteException {
    try {
      SoundDefinition def;

      if (ResourceGeneratorUtil.baseName(resource).endsWith("mp3")) {
        // MP3's are special-cased
        def = MP3Helper.getSoundDefinition(resource.openStream());

      } else {
        // Otherwise, fall back to a helper based on javax.sound
        ADPCMHelper helper = new ADPCMHelper(resource.openStream(), 30);
        def = helper.getSoundDefinition();
      }

      sounds.put(name, def);
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Unable to open resource", e);
      throw new UnableToCompleteException();
    } catch (UnsupportedAudioFileException e) {
      logger.log(TreeLogger.ERROR, "Unsupported audio format", e);
      throw new UnableToCompleteException();
    }
  }

  /**
   * Return the duration in seconds of the named sound.
   */
  public long getDuration(String name) {
    SoundDefinition def = sounds.get(name);
    switch (def.frequency) {
      case SWFConstants.SOUND_FREQ_44KHZ:
        return 1000L * def.sampleCount / 44000;
      case SWFConstants.SOUND_FREQ_22KHZ:
        return 1000L * def.sampleCount / 22000;
      case SWFConstants.SOUND_FREQ_11KHZ:
        return 1000L * def.sampleCount / 11000;
      case SWFConstants.SOUND_FREQ_5_5KHZ:
        return 1000L * def.sampleCount / 5500;
      default:
        return -1;
    }
  }

  /**
   * Returns the order in which the sounds will have been encoded into the sound
   * bundle. This method is valid only after
   * {@link #writeBundle(TreeLogger, ResourceContext)} has been called.
   */
  public int getIndex(String name) {
    return orderedSounds.indexOf(sounds.get(name));
  }

  /**
   * Finalize the sound bundle and write it into the output.
   *
   * @return A Java expression that will evaluate to the location of the sound
   *         bundle at runtime.
   */
  public String writeBundle(TreeLogger logger, ResourceContext context)
      throws UnableToCompleteException {

    // Sort the sounds from shortest to longest.
    orderedSounds.addAll(sounds.values());
    Collections.sort(orderedSounds, new Comparator<SoundDefinition>() {
      public int compare(SoundDefinition o1, SoundDefinition o2) {
        return o1.soundData.length - o2.soundData.length;
      }
    });

    // Get a handle to the SoundKernel app
    InputStream in = getClass().getClassLoader().getResourceAsStream(
        "com/google/gwt/libideas/resources/rg/SoundKernel.swf");
    if (in == null) {
      logger.log(TreeLogger.ERROR, "Could not load SoundKernel.swf", null);
      throw new UnableToCompleteException();
    }

    ByteArrayOutputStream out = new ByteArrayOutputStream();

    // Set up the processing chain
    SWFWriter writer = new SWFWriter(out);
    Appender ins = new Appender(writer);
    TagParser parser = new TagParser(ins);
    SWFReader reader = new SWFReader(parser, in);

    // Try running the chain
    try {
      reader.readFile();
    } catch (IOException e) {
    }

    // Write the completed sound bundle into the output
    return context.addToOutput(
        context.getResourceBundleType().getQualifiedSourceName()
            + ".SoundBundle.swf", "application/x-shockwave-flash",
        out.toByteArray(), true);
  }
}
TOP

Related Classes of com.google.gwt.libideas.resources.rg.SoundBundleBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.