> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-es/escenas-sdk7/media/audio-analysis.md).

# Análisis de Audio

El `AudioAnalysis` component lee datos en tiempo real de una fuente de audio que se reproduce en tu scene, así que puedes controlar elementos visuales a partir de la música. En cada frame, informa de una **amplitude** valor y **8 bandas de frecuencia** (de baja a alta) que puedes usar para escalar, colorear o animar entities.

Usos comunes:

* Cubos que rebotan con el bajo.
* Luces que pulsan con el ritmo.
* Visualizadores de barras al estilo ecualizador.
* Materiales reactivos o props escalados que coinciden con la música.

`AudioAnalysis` es un feed de solo lectura: tu scene solo consume los valores; el runtime los completa. Funciona en entities que reproducen audio mediante un [AudioSource](/creator/content-creator-es/escenas-sdk7/conceptos-basicos-de-contenido-3d/sounds.md), un [AudioStream](/creator/content-creator-es/escenas-sdk7/media/audio-streaming.md), o el audio de un [VideoPlayer](/creator/content-creator-es/escenas-sdk7/media/video-playing.md).

{% hint style="warning" %}
**📔 Nota**: `AudioAnalysis` solo está soportado actualmente por la app de escritorio oficial de Decentraland. En otros clients, los valores del component nunca se completan, así que asegúrate de que tu scene siga funcionando aunque los datos nunca lleguen.
{% endhint %}

## Ejemplo mínimo

La siguiente scene reproduce un sonido y adjunta `AudioAnalysis` al mismo entity, y escala un cubo en cada frame usando la amplitude del audio.

```ts
import {
  engine,
  Transform,
  MeshRenderer,
  AudioSource,
  AudioAnalysis,
  AudioAnalysisView,
} from "@dcl/sdk/ecs";
import { Vector3 } from "@dcl/sdk/math";

export function main() {
  // Reproduce un sonido en un entity
  const audioEntity = engine.addEntity();
  Transform.create(audioEntity);
  AudioSource.create(audioEntity, {
    audioClipUrl: "sounds/music.mp3",
    playing: true,
    loop: true,
  });

  // Adjunta AudioAnalysis al mismo entity para empezar a recibir datos de análisis
  AudioAnalysis.createAudioAnalysis(audioEntity);

  // Un objeto de vista reutilizable en el que el component escribirá en cada frame
  const analysis: AudioAnalysisView = {
    amplitude: 0,
    bands: new Array<number>(8),
  };

  // Un cubo que pulsa con la amplitude del audio
  const cube = engine.addEntity();
  MeshRenderer.setBox(cube);
  Transform.create(cube, { position: Vector3.create(8, 1, 8) });

  // En cada frame, lee los valores de análisis más recientes y escala el cubo
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
    const s = 1 + analysis.amplitude * 10;
    Transform.getMutable(cube).scale = Vector3.create(s, s, s);
  });
}
```

Las llamadas clave son:

1. `AudioAnalysis.createAudioAnalysis(entity)` — adjunta el component al entity que posee el `AudioSource`, `AudioStream`, o `VideoPlayer`. Por defecto usa el modo logarítmico (consulta [Modes](#modes)).
2. `AudioAnalysis.readIntoView(entity, analysis)` — copia los últimos `amplitude` y 8 `bands` valores en un objeto de vista que proporcionas.

{% hint style="warning" %}
**📔 Nota**: Preasigna siempre el `bands` array con **8 elementos** antes de llamar a `readIntoView`. El component no redimensiona el array por ti.
{% endhint %}

## Leer los datos en cada frame

`AudioAnalysis` está diseñado para leerse una vez por frame desde un System. El patrón recomendado es:

1. Asigna un único `AudioAnalysisView` objeto una vez.
2. En un System, llama a `readIntoView` para actualizarlo.
3. Usa los valores directamente, o comparte la vista entre varios systems.

```ts
const analysis: AudioAnalysisView = {
  amplitude: 0,
  bands: new Array<number>(8),
};

engine.addSystem(() => {
  AudioAnalysis.readIntoView(audioEntity, analysis);
  // analysis.amplitude y analysis.bands[0..7] ahora contienen los valores más recientes
});
```

Si el entity analizado podría no tener todavía un `AudioAnalysis` component (por ejemplo, se crea más tarde o se elimina dinámicamente), usa `tryReadIntoView` en su lugar. Devuelve `false` cuando el component falta, y `true` cuando se escribieron valores.

```ts
engine.addSystem(() => {
  if (!AudioAnalysis.tryReadIntoView(audioEntity, analysis)) return;
  // seguro usar analysis aquí
});
```

{% hint style="info" %}
**💡 Consejo**: Es más barato llamar a `readIntoView` una vez y dejar que varios systems compartan el mismo objeto de vista que leer el component repetidamente.
{% endhint %}

## Reacciona a bandas de frecuencia específicas

Las 8 bands cubren el espectro audible de baja a alta. `bands[0]` es la más baja (bass) y `bands[7]` es la más alta (treble). Puedes controlar diferentes entities desde diferentes bands para construir un ecualizador clásico.

```ts
import {
  engine,
  Transform,
  MeshRenderer,
  Material,
  AudioSource,
  AudioAnalysis,
  AudioAnalysisView,
  Schemas,
} from "@dcl/sdk/ecs";
import { Color4, Vector3 } from "@dcl/sdk/math";

// Component personalizado para marcar cada barra y recordar qué band sigue
const VisualBar = engine.defineComponent("visual-bar", {
  index: Schemas.Number,
});

const BARS_HEIGHT = 12;

export function main() {
  const audioEntity = engine.addEntity();
  Transform.create(audioEntity);
  AudioSource.create(audioEntity, {
    audioClipUrl: "sounds/music.mp3",
    playing: true,
    loop: true,
  });
  AudioAnalysis.createAudioAnalysis(audioEntity);

  const analysis: AudioAnalysisView = {
    amplitude: 0,
    bands: new Array<number>(8),
  };

  // Crea 8 barras, una por band
  for (let i = 0; i < 8; i++) {
    const bar = engine.addEntity();
    VisualBar.create(bar, { index: i });
    Transform.create(bar, { position: Vector3.create(4 + i, 0, 8) });
    MeshRenderer.setBox(bar);
    Material.setPbrMaterial(bar, { albedoColor: Color4.Yellow() });
  }

  // Leer una vez por frame
  engine.addSystem(() => {
    AudioAnalysis.readIntoView(audioEntity, analysis);
  });

  // Escala cada barra con su band
  engine.addSystem(() => {
    for (const [entity] of engine.getEntitiesWith(VisualBar, Transform)) {
      const index = VisualBar.get(entity).index;
      const transform = Transform.getMutable(entity);
      transform.scale = Vector3.create(
        1,
        analysis.bands[index] * BARS_HEIGHT,
        1
      );
    }
  });
}
```

Este es el mismo patrón usado en la [scene de ejemplo de visualización de audio](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/88,-10-audio-visualization), reducido a lo esencial.

## Modes

`AudioAnalysis` admite dos modos de análisis, que se establecen al crear el component:

* `PBAudioAnalysisMode.MODE_LOGARITHMIC` (predeterminado): los valores se escalan con una curva logarítmica, que se aproxima más a cómo el oído humano percibe los cambios de volumen. Ideal para la reactividad visual.
* `PBAudioAnalysisMode.MODE_RAW`: la amplitude sin procesar y los valores de bandas FFT. Usa esto si quieres aplicar tu propio escalado.

```ts
import { AudioAnalysis, PBAudioAnalysisMode } from "@dcl/sdk/ecs";

// Usa valores raw
AudioAnalysis.createAudioAnalysis(audioEntity, PBAudioAnalysisMode.MODE_RAW);
```

### Ajustar el modo logarítmico

En modo logarítmico puedes pasar dos multiplicadores de ganancia opcionales:

* `amplitudeGain` — multiplicador aplicado a la amplitude general. Por defecto `5`.
* `bandsGain` — multiplicador aplicado a las 8 bands. Por defecto `0.05`.

Las ganancias más altas hacen que los valores sean más reactivos; las más bajas los hacen más sutiles.

```ts
// Reacción de la amplitude más fuerte, reacción de bands más suave
AudioAnalysis.createAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_LOGARITHMIC,
  10, // amplitudeGain
  0.03 // bandsGain
);
```

{% hint style="warning" %}
**📔 Nota**: `amplitudeGain` y `bandsGain` solo se aplican en modo logarítmico. En modo raw se ignoran.
{% endhint %}

## Reemplazar un component existente

`createAudioAnalysis` falla si el entity ya tiene un `AudioAnalysis` component. Para cambiar modos o gains en runtime, usa `createOrReplaceAudioAnalysis`, que tiene la misma firma.

```ts
// Cambiar a modo raw a mitad de la scene
AudioAnalysis.createOrReplaceAudioAnalysis(
  audioEntity,
  PBAudioAnalysisMode.MODE_RAW
);
```

## Referencia del component

### `AudioAnalysis.createAudioAnalysis(entity, mode?, amplitudeGain?, bandsGain?)`

Adjunta un `AudioAnalysis` component a `entity`. Falla si ya hay un component presente.

* `entity` (`Entity`): la entity que posee el `AudioSource`, `AudioStream`, o `VideoPlayer` que quieres analizar.
* `mode` (`PBAudioAnalysisMode`, opcional): `MODE_LOGARITHMIC` (predeterminado) o `MODE_RAW`.
* `amplitudeGain` (`number`, opcional): multiplicador de amplitude en modo logarítmico. Por defecto `5`.
* `bandsGain` (`number`, opcional): multiplicador de bands en modo logarítmico. Por defecto `0.05`.

### `AudioAnalysis.createOrReplaceAudioAnalysis(entity, mode?, amplitudeGain?, bandsGain?)`

Igual que arriba, pero reemplaza un `AudioAnalysis` component existente en el entity en lugar de fallar.

### `AudioAnalysis.readIntoView(entity, out)`

Lee los valores más recientes en `out`. Lanza un error si `entity` no tiene un `AudioAnalysis` component.

* `entity` (`Entity`): la entity con el component.
* `out` (`AudioAnalysisView`): un objeto de vista que proporcionas. Debe tener `bands` preasignado con 8 numbers.

### `AudioAnalysis.tryReadIntoView(entity, out): boolean`

Igual que `readIntoView`, pero devuelve `false` si el entity no tiene un `AudioAnalysis` component en lugar de lanzar un error. Devuelve `true` cuando se escriben valores.

### `AudioAnalysisView`

Un objeto simple que asignas para recibir los datos de análisis:

```ts
type AudioAnalysisView = {
  amplitude: number; // strength general de la señal
  bands: number[]; // 8 bandas de frecuencia, de baja (0) a alta (7)
};
```

## Notas y limitaciones

* **8 bands, fijas.** El número de bandas de frecuencia está fijado en 8. No hay ninguna API para pedir más o menos bands.
* **Una fuente de audio por análisis.** Cada `AudioAnalysis` component analiza el audio del entity al que está adjunto. Para analizar varias fuentes, adjunta `AudioAnalysis` a cada una.
* **El audio en pausa no reporta actualizaciones.** Cuando el audio subyacente se detiene o se pausa, los valores del component dejan de cambiar. Los últimos valores leídos permanecen en tu objeto de vista hasta que el audio vuelva a reproducirse.
* **Barato, pero no gratis.** El análisis por frame está diseñado para ser económico (sub-milisegundo por source en desktop). Evita adjuntar `AudioAnalysis` a demasiadas sources a la vez si no necesitas los datos. Elimina el component cuando un visualizer no sea visible.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-es/escenas-sdk7/media/audio-analysis.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
