Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Trucos (https://www.clubdelphi.com/foros/forumdisplay.php?f=52)
-   -   Mezclando (Fading) 2 Canales (Streams) con BASS Lib (https://www.clubdelphi.com/foros/showthread.php?t=97474)

navbuoy 21-05-2025 23:43:59

Mezclando (Fading) 2 Canales (Streams) con BASS Lib
 
�� Requisitos

bass.dll (en la carpeta del .exe)

bass.h y bass.lib enlazados al proyecto

Dos archivos MP3 válidos (ej: tema1.mp3 y tema2.mp3)

Un TTimer en tu formulario (llamalo FadeTimer) con Interval = 50


�� Resultado

Esto hace un crossfade suave de 8 segundos entre dos MP3 en tiempo real, sin detener la reproducción, y sin usar un mezclador complejo.

Declaraciones en Form1.h por ejemplo...

Código:

HSTREAM stream1, stream2;
float volume1 = 1.0f;
float volume2 = 0.0f;
int fadeStepCount = 0;
const int fadeTotalSteps = 160; // 8 segundos / 0.05s = 160 pasos


Código:

void __fastcall TForm1::StartCrossfade()
{
    if (!BASS_Init(-1, 44100, 0, Handle, NULL))
    {
        ShowMessage("No se pudo inicializar BASS");
        return;
    }

    // Cargar los dos MP3
    stream1 = BASS_StreamCreateFile(FALSE, "C:\\audio\\tema1.mp3", 0, 0, 0);
    stream2 = BASS_StreamCreateFile(FALSE, "C:\\audio\\tema2.mp3", 0, 0, 0);

    if (!stream1 || !stream2)
    {
        ShowMessage("Error cargando los MP3");
        return;
    }

    // Seteamos volumen inicial
    BASS_ChannelSetAttribute(stream1, BASS_ATTRIB_VOL, 1.0f);
    BASS_ChannelSetAttribute(stream2, BASS_ATTRIB_VOL, 0.0f);

    // Reproducimos ambos
    BASS_ChannelPlay(stream1, FALSE);
    BASS_ChannelPlay(stream2, FALSE);

    // Iniciar timer
    volume1 = 1.0f;
    volume2 = 0.0f;
    fadeStepCount = 0;
    FadeTimer->Enabled = true;
}


�� Código del FadeTimer (cada 50ms):
Código:

void __fastcall TForm1::FadeTimerTimer(TObject *Sender)
{
    fadeStepCount++;

    float stepSize = 1.0f / fadeTotalSteps;

    volume1 -= stepSize;
    volume2 += stepSize;

    if (volume1 < 0.0f) volume1 = 0.0f;
    if (volume2 > 1.0f) volume2 = 1.0f;

    BASS_ChannelSetAttribute(stream1, BASS_ATTRIB_VOL, volume1);
    BASS_ChannelSetAttribute(stream2, BASS_ATTRIB_VOL, volume2);

    if (fadeStepCount >= fadeTotalSteps)
    {
        FadeTimer->Enabled = false;

        // (Opcional) Detener stream1 si ya terminó el crossfade
        BASS_ChannelStop(stream1);
    }
}

⏱️ ¿Por qué 160 pasos?
Interval = 50ms (0.05s por paso)

8s / 0.05s = 160 pasos

Entonces cada paso debe cambiar el volumen por 1 / 160 = 0.00625

navbuoy 21-05-2025 23:52:50

Si lo que queremos es alternar entre stream1 y stream2 constantemente con crossfades de 8 segundos, lo que necesitás es algo como un sistema de doble canal con fading automático, donde uno sube mientras el otro baja, y viceversa.

Mantenemos ambos streams en loop o reproducibles.

Creamos un estado booleano currentIsStream1 para saber cuál está "activo".

Cada vez que quieras hacer crossfade, inviertes el estado y disparas el timer.

🔸 Variables globales:

Código:

HSTREAM stream1, stream2;
float volume1, volume2;
int fadeStepCount = 0;
const int fadeTotalSteps = 160;
bool currentIsStream1 = true;  // true = stream1 activo, false = stream2


🔸 Al iniciar la app:

Código:

void __fastcall TForm1::StartStreams()
{
    BASS_Init(-1, 44100, 0, Handle, NULL);

    stream1 = BASS_StreamCreateFile(FALSE, "C:\\audio\\tema1.mp3", 0, 0, BASS_SAMPLE_LOOP);
    stream2 = BASS_StreamCreateFile(FALSE, "C:\\audio\\tema2.mp3", 0, 0, BASS_SAMPLE_LOOP);

    BASS_ChannelSetAttribute(stream1, BASS_ATTRIB_VOL, 1.0f);
    BASS_ChannelSetAttribute(stream2, BASS_ATTRIB_VOL, 0.0f);

    BASS_ChannelPlay(stream1, FALSE);
    BASS_ChannelPlay(stream2, FALSE);

    volume1 = 1.0f;
    volume2 = 0.0f;
    currentIsStream1 = true;
}

🔸 Función para iniciar el crossfade:

Código:

void __fastcall TForm1::StartCrossfade()
{
    fadeStepCount = 0;
    FadeTimer->Enabled = true;
}


🔸 Timer de crossfade:

Código:

void __fastcall TForm1::FadeTimerTimer(TObject *Sender)
{
    fadeStepCount++;
    float stepSize = 1.0f / fadeTotalSteps;

    if (currentIsStream1)
    {
        volume1 -= stepSize;
        volume2 += stepSize;
    }
    else
    {
        volume1 += stepSize;
        volume2 -= stepSize;
    }

    // Clamp
    if (volume1 < 0.0f) volume1 = 0.0f;
    if (volume1 > 1.0f) volume1 = 1.0f;
    if (volume2 < 0.0f) volume2 = 0.0f;
    if (volume2 > 1.0f) volume2 = 1.0f;

    BASS_ChannelSetAttribute(stream1, BASS_ATTRIB_VOL, volume1);
    BASS_ChannelSetAttribute(stream2, BASS_ATTRIB_VOL, volume2);

    if (fadeStepCount >= fadeTotalSteps)
    {
        FadeTimer->Enabled = false;
        currentIsStream1 = !currentIsStream1;
    }
}


🔸 Para automatizar el cambio cada X segundos:
Agrega un segundo TTimer (llamalo AutoSwitchTimer) con Interval = 30000 (por ejemplo, 30 segundos), y su código sería:

Código:

void __fastcall TForm1::AutoSwitchTimerTimer(TObject *Sender)
{
    StartCrossfade();
}


Casimiro Noteví 22-05-2025 01:16:32

^\||/^\||/^\||/

Neftali [Germán.Estévez] 22-05-2025 09:30:45

Gracias por el código.
^\||/


La franja horaria es GMT +2. Ahora son las 06:30:15.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi