Criar
um objeto de som em Flash é fácil, na teoria. Importe
um arquivo wav (ou outro formato de som de sua escolha, desde que seja
suportado pelo Flash), dê a ele um nome de exportação,
crie um movieclip em branco para contê-lo, e edite uns poucos
comandos para criar e controlar o som. O tutorial Sound
Object,
nessa mesma seção, explica como fazer isso.
Criar
um mix de sons juntos e pré-carregados, mantê-los em sincronia
e controlar o volume de cada intervalo requer um pouco mais de trabalho
(Muito mais trabalho, de fato - eu só consegui que essa coisa
trabalhasse finalmente graças às sugestões e habilidades
para resolver problemas dos gurus do som Martin Fasani e Muzak).
A idéia desse exemplo foi simples: criar uma
maneira para o usuário mixar juntos loops do mesmo comprimento
(ou múltiplos daquele comprimento) em volumes variáveis
para criar um novo loop. Para fazer isto, os intervalos devem ser mostrados
graficamente e um meio deve ser fornecido para que o volume de cada
um deles seja ajustado. Um botão para tocar deve permitir alternar
entre tocar através dos intervalos em níveis especificados
de volume e parar o som para outros ajustes de volume.
A "interface gráfica" é simplesmente
uma seqüência de imagens bitmap de cada loop de som dispostos
juntos sobre seis intervalos. O controle de volume consiste de um mostrador
do volume atual e botões para aumentar e diminui-lo em incrementos
de 10. O filme que hospeda o som é carregado no nível
1, e, quando é carregado, o filme da interface gráfica
mostra os intervalos dos loops, com os volumes padrões exibidos,
permitindo ao usuário, ou clicar Play para testá-lo como
está, ou ajustar o volume de qualquer intervalo e então
clicar Play. É necessário fazer os ajustes antes de pressionar
o play. Um contorno amarelo mostra qual intervalo está tocando
atualmente:
Para
criar o filme que conterá os sons na biblioteca e os movieclips
hospedeiros em branco no palco
O
primeiro passo na criação dessa coisa foi fazer o som
swf (f5as_soundloops.fla). Em um filme em branco, importei três
arquivos de som wave (Arquivo (File), Importar (Import), o que coloca
os arquivos na biblioteca dos filmes) e dei a eles nomes de exportação
(clicando o botão direito do mouse no item biblioteca, escolhi
Vinculação (Linkage), e marquei Exportar (Export)) expDrums,
expRandb e expEth. Criei então um movieclip em
branco (Control-F8), voltei à linha de tempo de trás e
a apaguei do palco. Da biblioteca, arrastei três cópias
do movieclip em branco sobre o palco dando a eles os nomes de instância
mcHolder0, mcHolder1, e mcHolder2. Os objetos de
som não são criados nesse swf, que somente os hospeda.
Esse filme de quadro único foi editado como f5as_soundloops.swf.
Para
criar o filme que utilizará o arquivo de som para fazer um mixer
O
cerne do exemplo é o soundcontroller.fla. Este filme carrega
o som do soundloops.swf, cria objetos de som personalizados, e os toca,
controlando o volume a cada intervalo. (Nessa versão, o volume
permanece constante em cada intervalo, mas o código pode ser
ajustado para executar desvanecimentos (fades) e envolvimento (enveloping)).
Primeiro, dois objetos personalizados - MixedLoop
e MixedLoopComponent - são definidos junto com seus métodos.
O MixedLoopComponent é um som individual com propriedades
que definem sua origem, seu movieclip hospedeiro e uma série
de volumes para cada intervalo. O MixedLoop é um objeto
que é uma coleção de MixedLoopComponents.
Suas propriedades incluem o número de intervalos no loop final,
o comprimento em milisegundos de um intervalo individual, a série
do MixedLoopComponents, um indicador de quando ele está
tocando ou não e a linha de tempo na qual o objeto existe. Este
é o código usado para definir e criar esses objetos:
Define o objeto e suas propriedades
Essa é a função construtora para o objeto MixedLoopComponent:
Define as funções que se tornarão métodos
do objeto
Esses são os métodos-de-ser para o objeto MixedLoopComponent,
que controla sua criação, partida, parada e volume:
function
mlcDefineSound(sndName, attSoundID) {
this[sndName] = new Sound(this.mcHolder);
this[sndName].attachSound(attSoundID);
}
function
mlcStartSound(sndName, nDelay, nLoops) {
this[sndName].start(nDelay, nLoops);
this.chgVolume(sndName, 0);
}
function
mlcChgVolume (sndName, nVolume) {
this[sndName].setVolume(nVolume);
}
function
mlcStopSound(sndName) {
this[sndName].stop();
}
Crie métodos das funções
Essa instrução determina as funções acima
como métodos do objeto (usando uma convenção "nomeadora"
como esquematizado por Robin Debreuil, que torna fácil manter o
rastreamento dos nomes de método e suas funções relacionadas):
Uma instrução similar define o objeto MixedLoop,
que seria uma coleção de MixedLoopComponents e inclui
esse método para iniciar todos:
function
mlStartAll() {
this.nIntCount = 0;
for (i=0; i < this.aSounds.length; i++) {
this.aSounds[i].startSound(this.aSounds[i].sName,
0, 99);
}
// start-stop-start necessary for syncing after a stop
for (i=0; i < this.aSounds.length; i++) {
this.aSounds[i].stopSound(this.aSounds[i].sName,
0, 99);
}
for (i=0; i < this.aSounds.length; i++) {
this.aSounds[i].startSound(this.aSounds[i].sName,
0, 99);
}
this.startTime = 0 - (this.nIntMs);
this.lStarted = true;
}
Note que cada um é iniciado, depois parado, para então iniciar
novamente - isso é necessário para manter os loops em sincronia
após pará-los. (Tente remover o stopSound e startSound
dos loops para ver como eles soam sem isto!)
Crie
instâncias do(s) objeto(s)
O passo final na criação da configuração
para o soundcontroller é criar instâncias dos objetos:
//
Create instances of MixedLoopComponents
aLoops = new Array(3);
aLoops[0] = new MixedLoopComponent("drums", "expDrums",
aDefaultVolumes[0], "_level1.mcHolder0");
aLoops[1] = new MixedLoopComponent("randb", "expRandB",
aDefaultVolumes[1], "_level1.mcHolder1");
aLoops[2] = new MixedLoopComponent("eth", "expEth",
aDefaultVolumes[2], "_level1.mcHolder2");
//
Create MixedLoop object from components
mlExperimental = new MixedLoop(aLoops, 8, 6, this);
mlExperimental.attachSounds();
Uma vez que o MixedLoop tenha sido criado (incluindo
a especificação do comprimento do intervalo - neste caso,
8 segundos), o filme põe-se em estado de espera até que
o usuário pressione Play (um botão em um movieclip de dois
estados). Isto adapta a série de volumes baseado no valor corrente
em cada movieclip volume, inicia o som, coloca o contorno amarelo na posição
de iniciar e então pára no quadro "started"
até que o usuário clique em Stop.
Enquanto isso, um movieclip controlador em branco assume
o controle, monitorando até o fim de um intervalo, ajustando o
volume, o contador de intervalo e o esboço amarelo adequadamente,
quando um novo intervalo inicia:
onClipEvent(load)
{
var mlrExp = _parent.mlExperimental;
}
onClipEvent(enterFrame)
{
if (mlrExp.lStarted && (getTimer() -
mlrExp.startTime >= mlrExp.nIntMs)) {
// start next interval
for (i=0; i < mlrExp.aSounds.length;
i++) {
mlrExp.aSounds[i].chgVolume(mlrExp.aSounds[i].sName,
mlrExp.aSounds[i].aVol[mlrExp.nIntCount]);
}
_parent.mcYellow._x = _parent.nOutlineStart
+ (mlrExp.nIntCount * 75);
mlrExp.nIntCount++;
if (mlrExp.nIntCount >=
mlrExp.nTotalInt) {
mlrExp.nIntCount
= 0
}
mlrExp.startTime = getTimer();
// reset for next interval
}
}
É isso para os elementos desse filme, exceto
pelo pré-carregamento. Porque o som é muito grande usualmente
e quaisquer sons exportados são carregados antes de que qualquer
filme possa executar, é uma boa idéia colocar os sons em
um filme e fazer o pré-carregamento em outro, então o usuário
não vê uma tela em branco enquanto os sons anexados carregam.
No soundcontroller.fla, isto é feito pelo carregamento do
soundloop.swf no nível 1 e utilizando um movieclip com este
código para monitorar um carregamento completo (e mostrar o percentual
corrente carregado enquanto isso):
onClipEvent(load)
{
_root.nPercent = 0;
}
onClipEvent(enterFrame)
{
// check for some loading so getBytesTotal doesn't
return 0 and set nPercent to NaN
if (_level1.getBytesLoaded()>1)
{
if (_level1.getBytesLoaded()
>= _level1.getBytesTotal()) {
_root.gotoAndPlay("readyStart");
}
_root.nPercent
= Math.round(_level1.getBytesLoaded() / _level1.getBytesTotal()
* 100);
}
}
O
quadro marcado readyStart contém todo o código
acima que define os objetos, etc.
Tradução:
Sérgio Ramalho
Devido à reformulação implementada no site, pode ser que você encontre alguns links quebrados. Por favor, ajude-nos a corrigir eventuais problemas nos informando links quebrados