sábado, 18 de septiembre de 2010

Generar imagen de un archivo de música

Hoy voy a mostrar el código fuente de un programa que hice y que, como se ve en la imagen de abajo, genera una imagen a partir de un archivo de música.

El programa no es de mas de 80 lineas, y usa la librería "Bass" para leer los archivos de música y "easyBMP" para generar la imagen.

Seguramente muchos estaréis pensando que bmp es peor que, por ejemplo,  png o jpg, pero aunque ocupe mas es el mas fácil y simple. Por otro lado, el programa esta sin optimizar, y seguramente tenga algunos pequeños fallos.

Descargar

#include "bass.h"
#include "EasyBMP.h"
using namespace std;

#define WIDTH 1520
#define HEIGHT 150

int main(int argc, char* file[])
{
    if (argc < 2)
        cout << "Usage Music2bmp file1.mp3 ... fileX.ext" << endl;
    else if (HIWORD(BASS_GetVersion())!=BASSVERSION)
        cout << "An incorrect version of BASS.DLL was loaded" << endl;
    else if (!BASS_Init(-1,44100,0,0,NULL))
        cout << "Can't initialize device" << endl;
    else
    {
        for (int z=1; z<argc; z++)
        {
            cout << "      "<< file[z];

            DWORD chan;
            if (!(chan = BASS_StreamCreateFile(FALSE,file[z],0,0,BASS_STREAM_DECODE)) &&
                    !(chan = BASS_MusicLoad(FALSE,file[z],0,0,BASS_MUSIC_DECODE,0)))
            {
                cout << '\r' << "ERROR " << endl; //load error
                continue;
            }

            BMP img;
            img.SetSize(WIDTH,HEIGHT);
            img.SetBitDepth(24);

            DWORD bpp = BASS_ChannelGetLength(chan,BASS_POS_BYTE)/WIDTH;
            DWORD cpos=0, peak[2]= {0}, n=0, pos=0, level;

            do
            {
                level = BASS_ChannelGetLevel(chan);
                n++;
                peak[0] = (peak[0]*(n-1)+LOWORD(level))/n;
                peak[1] = (peak[1]*(n-1)+HIWORD(level))/n;
                pos = BASS_ChannelGetPosition(chan,BASS_POS_BYTE)/bpp;
                if (pos>cpos)
                {
                    for (DWORD a=0,b=peak[0]*(HEIGHT/2)/32768; a<b; a++)
                    {
                        img(cpos, HEIGHT/2-a-1)->Red = (BYTE) (a+b);
                        img(cpos, HEIGHT/2-a-1)->Green = (BYTE) (a*1.75+b*1.25);
                        img(cpos, HEIGHT/2-a-1)->Blue = (BYTE) (a*2.5+b);
                    }
                    for (DWORD a=0,c=peak[1]*(HEIGHT/2)/32768; a<c; a++)
                    {
                        img(cpos, HEIGHT/2+a)->Red = (BYTE) (a+c*1.25);
                        img(cpos, HEIGHT/2+a)->Green = (BYTE) (a*1.75+c);
                        img(cpos, HEIGHT/2+a)->Blue = (BYTE) (a*2.5+c);
                    }
                    cout << '\r' << (pos*100)/WIDTH << '%';
                    cpos = pos;
                    peak[0]=peak[1]=n=0;

                }
            }
            while (pos<WIDTH);
            BASS_StreamFree(chan);
            Rescale(img,'W',WIDTH/2);

            char * out = new char[strlen(file[z])+4];
            strcpy(out,file[z]);
            strcat (out,".bmp");
            img.WriteToFile(out);
            delete [] out;
            cout << '\r' << "OK    " << endl;
        }
        BASS_Free();
    }
    system("pause");
    return 0;
}

Comparte o puntua esta publicación ▼

0 comentarios:

Publicar un comentario