Форум » GUI » Поговорим о музыке? » Ответить

Поговорим о музыке?

SADSTAR2: задумал вставить фоновую музыку. исходник музыки - ~1Mb mp3 Стал изучать возможные варианты. 1. PLAY WAVE <cWaveName> [ FROM RESOURCE ] играет только wav. Преобразовал 1Мб mp3 в 11Мб wav. Включил в ресурсы. Компилитор ругается. >Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland >Fatal: Access violation. Link terminated. Похоже на ограничение на размер ресурса, т.к. короткий Wav ~50kb съел без вопросов. Это не преодолимо? Не хочется иметь отдельный файл. Можно ли скормить команде PLAY WAVE не имя файла или ресурса, а memo-переменную (которую загрузить BLOB-ом из базы данных)? 2.мысли - Использовать PLAYER в невидимом режиме. Он играет mp3? Можно ли задать ему имя ресурса или memo-переменную? И хотя нет такого типа ресурса как mp3, можно попробовать обмануть - сказать wav, а подсунуть mp3. Или есть тип AVI. Создать avi из одного mp3. А PLAYER играет avi?

Ответов - 5

gfilatov: SADSTAR2 пишет: задумал вставить фоновую музыку. исходник музыки - ~1Mb mp3 Попробуй следующий класс для проигрывания MP3-файлов: /****************************************************************************** Programa: TMp3 class Vesion: 1.0 (c) Cristobal Molla [cemese@terra.es] ******************************************************************************/ #include "hbclass.ch" #include "directry.ch" #define BUFFER 200 #define CRLF hb_OsNewLine() #define TRUE .T. #define FALSE .F. #define MCI_MODE_UNKNOW 0 #define MCI_MODE_NOTREADY 1 #define MCI_MODE_PAUSED 2 #define MCI_MODE_PLAYING 3 #define MCI_MODE_STOPPED 4 CLASS TMp3 DATA nId INIT 0 DATA nStatus INIT 0 DATA lOpened INIT FALSE METHOD ERROR( nError, cMetodo ) METHOD New() METHOD Open( cFile ) METHOD Close() METHOD Status() METHOD Play() METHOD Stop() ENDCLASS METHOD ERROR( nError, cMetodo ) CLASS TMp3 // Declaracion de variables.------------------------------------------- LOCAL cError as character LOCAL cTexto as character // Inicializacion de variables.---------------------------------------- cError := Space( BUFFER ) // Muestra el mensaje de error.---------------------------------------- MCIGetErrorString( nError, @cError ) IF Empty( cError ) cTexto := "Error desconocido al ejecutar el comando " cTexto += cMetodo + " del dispositivo MP3 " + CRLF cTexto += CRLF cTexto += "Cуdigo de Error: " cTexto += hb_ValtoStr( nError ) ELSE cTexto := "Error al ejecutar el comando " cTexto += cMetodo + " del dispositivo MP3 " + CRLF cTexto += CRLF cTexto += "Cуdigo de Error: " cTexto += hb_ValtoStr( nError ) + CRLF cTexto += "Error: " + cError + " " + CRLF CTexto += "Llamado desde: " + ProcName( 2 ) ENDIF MsgInfo( cTexto, "Atenciуn" ) RETURN NIL METHOD New() CLASS TMp3 ::nId := 0 ::nStatus := MCI_MODE_UNKNOW ::lOpened := FALSE RETURN self METHOD Open( cFile ) CLASS TMp3 // Declaracion de variables.------------------------------------------- LOCAL cFileName as character LOCAL nError as numeric LOCAL cComando as character LOCAL cReturn as character // Control de parametros.---------------------------------------------- IF !File( cFile ) MsgInfo( "No existe el archivo " + cFile, "TMp3 Class" ) RETURN ::lOpened ENDIF // Inicializacion de variables.---------------------------------------- cFileName := _GetShortPathName( cFile ) cComando := "OPEN " + cFileName + " TYPE MPEGVIDEO ALIAS MP3" cReturn := Space( BUFFER ) // Abre el fichero especificado.--------------------------------------- nError := MCISendString( cComando, @cReturn, GetActiveWindow() ) IF nError > 0 ::ERROR( nError, "TMp3:Open()" ) ELSE ::nId := MCIGetDeviceId( "MP3" ) ::nStatus := ::Status() ::lOpened := TRUE ENDIF RETURN ::lOpened METHOD Close() CLASS TMp3 // Declaracion de variables.------------------------------------------- LOCAL nError as numeric LOCAL cComando as character LOCAL cReturn as character // Inicializacion de variables.---------------------------------------- cComando := "CLOSE MP3" cReturn := Space( BUFFER ) // Obtiene el modo.---------------------------------------------------- nError := MCISendString( cComando, @cReturn, GetActiveWindow() ) IF nError > 0 ::ERROR( nError, "TMp3:Close()" ) ELSE ::lOpened := FALSE ENDIF RETURN ::lOpened METHOD Status() CLASS TMp3 // Declaracion de variables.------------------------------------------- LOCAL nError AS NUMERIC LOCAL cComando AS CHARACTER LOCAL cReturn AS CHARACTER // Inicializacion de variables.---------------------------------------- cComando := "STATUS MP3 MODE " cReturn := Space( BUFFER ) // Obtiene el modo.---------------------------------------------------- nError := MCISendString( cComando, @cReturn, GetActiveWindow() ) IF nError > 0 ::ERROR( nError, "TMp3:Status()" ) ELSE DO CASE CASE cReturn == "not ready" ::nStatus := MCI_MODE_NOTREADY CASE cReturn == "paused" ::nStatus := MCI_MODE_PAUSED CASE cReturn == "playing" ::nStatus := MCI_MODE_PLAYING CASE cReturn == "stopped" ::nStatus := MCI_MODE_STOPPED OTHERWISE ::nStatus := MCI_MODE_UNKNOW ENDCASE ENDIF RETURN cReturn METHOD Play() CLASS TMp3 // Declaracion de variables.------------------------------------------- LOCAL nError LOCAL cComando LOCAL cReturn // Inicializacion de variables.---------------------------------------- cComando := "PLAY MP3 FROM 1" cReturn := Space( BUFFER ) // Obtiene el modo.---------------------------------------------------- nError := MCISendString( cComando, @cReturn, GetActiveWindow() ) IF nError > 0 ::ERROR( nError, "TMp3:Play()" ) ELSE ENDIF RETURN NIL METHOD Stop() CLASS TMp3 // Declaracion de variables.------------------------------------------- LOCAL nError LOCAL cComando LOCAL cReturn // Inicializacion de variables.---------------------------------------- cComando := "STOP MP3" cReturn := Space( BUFFER ) // Obtiene el modo.---------------------------------------------------- nError := MCISendString( cComando, @cReturn, GetActiveWindow() ) IF nError > 0 ::ERROR( nError, "TMp3:Stop()" ) ELSE ENDIF RETURN NIL #pragma BEGINDUMP // Ficheros de definiciones de C. #include <windows.h> #include <mmsystem.h> #include <commctrl.h> #include <winuser.h> // Ficheros de definiciones de Harbour. #include "hbapi.h" /****************************************************************************** Procedimiento: MCISendString( cComando, cBuffer ) Parametros: cComando - Caracter. Comando a ejecutar. cBuffer - Caracter. Buffer para almacenar la respuesta del comando. Devuelve: Notas: Prototipo C: MCIERROR mciSendString( LPCTSTR lpszCommand, LPTSTR lpszReturnString, UINT cchReturn, HANDLE hwndCallback ); The mciSendString function sends a command string to an MCI device. The device that the command is sent to is specified in the command string. Parameters ---------- lpszCommand Address of a null-terminated string that specifies an MCI command string. For more information about the command strings, see Command Strings. lpszReturnString Address of a buffer that receives return information. If no return information is needed, this parameter can be NULL. cchReturn Size, in characters, of the return buffer specified by the lpszReturnString parameter. hwndCallback Handle of a callback window if the “notify” flag was specified in the command string. Return Values ------------- Returns zero if successful or an error otherwise. The low-order word of the returned doubleword value contains the error return value. If the error is device-specific, the high-order word of the return value is the driver identifier; otherwise, the high-order word is zero. For a list of possible error values, see Constants: MCIERR Return Values. To retrieve a text description of mciSendString return values, pass the return value to the mciGetErrorString function. ******************************************************************************/ HB_FUNC ( MCISENDSTRING ) { // Declaracion de variables.------------------------------------------- DWORD nError; //HWND hWindow := hb_parnl( 3 ); // Envio del comando.-------------------------------------------------- nError = mciSendString( hb_parc( 1 ), hb_parc( 2 ), hb_parcsiz( 2 ), (HWND) hb_parnl( 3 ) ); // Control de error.--------------------------------------------------- hb_retni( nError ); } /****************************************************************************** Procedimiento: MCIGetErrorString( nError, @cError ) Parametros: nError - Numerico. Numero del error devuelto por mciSendCommand() o mciSendString(). cError - Cadena de caracteres con el texto descriptivo del error. Inicializada. Pasada por referencia. Devuelve: lError - Logico. Verdadero si se encontro la descripcion del error, falso en caso contrario Notas: Devuelve la descripcion de error al enviar un comando MCI. Prototipo C: BOOL mciGetErrorString( DWORD fdwError, LPTSTR lpszErrorText, UINT cchErrorText ); The mciGetErrorString function retrieves a string that describes the specified MCI error code. Parameters ---------- fdwError Error code returned by the mciSendCommand or mciSendString function. lpszErrorText Address of a buffer that receives a null-terminated string describing the specified error. cchErrorText Length of the buffer, in characters, pointed to by the lpszErrorText parameter. Return Values ------------- Returns TRUE if successful or FALSE if the error code is not known. ******************************************************************************/ HB_FUNC ( MCIGETERRORSTRING ) { // Devuelve la descripcion del error.---------------------------------- hb_retl( mciGetErrorString( hb_parni( 1 ), hb_parc( 2 ), hb_parcsiz( 2 ) ) ); } /****************************************************************************** Procedimiento: MCIGetDeviceID() Parametros: cDispositivo - Caracter. Nombre del dispositivo o del alias abierto satisfactoriamente. Devuelve: El identificador con el nombre del dispositivo o su alias o cero si no esta abierto. Notas: Obtiene el identifiacdor de un dispositivo MCI. Prototipo C: MCIDEVICEID mciGetDeviceID( LPCTSTR lpszDevice ); The mciGetDeviceID function retrieves the device identifier corresponding to the name of an open device. Parameters ---------- lpszDevice Address of a null-terminated string that specifies the device name or the alias name by which the device is known. Return Values ------------- Returns the device identifier assigned to the device when it was opened if successful. The identifier is used in the mciSendCommand function. If the device name is not known, if the device is not open, or if there was not enough memory to complete the operation, the return value is zero. ******************************************************************************/ HB_FUNC ( MCIGETDEVICEID ) { // Obtiene el ID del dispositivo o alias MCI. hb_retni( mciGetDeviceID( hb_parc( 1 ) ) ); } #pragma ENDDUMP Тестовый пример для этого класса: #include "minigui.ch" Set Proc To tmp3.prg PROCEDURE Main() LOCAL oMp3 := TMp3():New() DEFINE window wndMain ; at 0, 0 ; width getdesktopwidth() ; height getdesktopheight() - 27 ; title "MP3 Test" ; main DEFINE main menu DEFINE popup "&Test MP3" menuitem " Open MP3 file and device" ; action {|| if( !oMp3:lOpened, ; oMp3:Open( getFile( { { "MP3", "*.mp3" } }, "Select File", CurDir(), FALSE, TRUE ) ), ) } menuitem " oMp3:Status()" ; action {|| if( oMp3:lOpened, MsgInfo( oMp3:Status() ), ) } menuitem " oMp3:Play()" ; action {|| if( oMp3:lOpened, oMp3:Play(), ) } menuitem " oMp3:Stop()" ; action {|| if( oMp3:lOpened, oMp3:Stop(), ) } menuitem " oMp3:Close()" ; action {|| if( oMp3:lOpened, oMp3:Close(), ) } END popup END menu END window activate window wndMain RETURN

SADSTAR2: Большое спасибо. Играет. Обычный PLAYER тоже играет mp3. И в режиме HIDE - как я и расчитывал. Но музыку берут оба из файла на диске. А я хотел из памяти. Нашел страницу с решением похожей задачи. http://www.firststeps.ru/mfc/mci/r.php?8 Но я практически не секу в Си. Может ты сможешь переложить это на Харборовский язык?

gfilatov: SADSTAR2 пишет: переложить это на Харборовский язык? SADSTAR2 пишет: Обычный PLAYER тоже играет mp3. Изменения, которые можно внести в source\c_media.c HB_FUNC( C_PLAYWAVE ) { int Style = SND_ASYNC; HMODULE hmod = NULL; if( hb_parl(2) ) { Style = Style | SND_MEMORY; } else { Style = Style | SND_FILENAME; } if( hb_parl(3) ) { Style = Style | SND_SYNC; } if( hb_parl(4) ) { Style = Style | SND_NOSTOP; } if( hb_parl(5) ) { Style = Style | SND_LOOP; } if( hb_parl(6) ) { Style = Style | SND_NODEFAULT; } hb_retl( PlaySound(hb_parc(1), hmod, Style) ); } и затем использовать стандартную команду SADSTAR2 пишет: PLAY WAVE <cWaveName> FROM RESOURCE Также не забудь загрузить весь проигрываемый файл в память Например, с помощью функции MemoRead()


SADSTAR2: Ок. Отладочный вариант работает. Загрузил wav-ы в базу sqlite. Извлекаю. Запускаю проигрывание. Останавливаю. Огорчает то, что база с примерно 2.5 МегБ распухла до 17. И ведь в ней большей частью - "воздух". Рассматривал идею сжать wav-ы zip-ом и разжимать перед воспроизведением. Но все zip-ы работают только через файлы на диске. А нужно чтобы только в памяти из одной переменной в другую перекодировал. Склоняюсь к мысли, что меньший размер важнее чистоты алгоритма. Т.е. хранить в базе mp3 и играть обычным плэйером из временного файла. Или может кто сгенерирует идею как подсунуть обычному PLAYER-у не файл а memo-переменную для проигрывания содержимого?

SergeyL: В ресурс можно включать любые файлы. Размер файла до 1 Mb. Извлечь ресурс в файл можно мспользуя функции API. Ниже пример. // RESTOFILE(cFileExe, cNameRes, cTypeRes, cFileOut) // cFileExe - файл с ресурсом // cNameRes - имя ресурса // cTypeRes - тип ресурса // cFileOut - выходн. файл // RESTOFILE( , "MP3_1", "MP3DATA", "1.mp3") #include <windows.h> #include "hbapi.h" HB_FUNC(RESTOFILE) { HRSRC hResLoad; HANDLE hExe; HRSRC hRes; HANDLE File ; LPVOID pData; DWORD dwSize; DWORD Written; int iRet=0; if(hb_parc( 1 ) == NULL) { hExe = GetModuleHandle(NULL); } else { hExe = LoadLibrary(hb_parc( 1 )); if(hExe == NULL) { iRet=1; } } if(iRet==0) { hRes = FindResource(hExe, hb_parc( 2 ), hb_parc( 3 )); if (hRes == NULL) { iRet=2; } } if(iRet==0) { hResLoad = LoadResource(hExe, hRes); if (hResLoad == NULL) { iRet=3; } } if(iRet==0) { dwSize = SizeofResource(hExe,hRes); if(dwSize == NULL) { iRet=4; } } if(iRet==0) { pData = LockResource(hResLoad); if(pData == NULL) { iRet=5; } } if(iRet==0) { File = CreateFile(hb_parc( 4 ),GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_ALWAYS,0,0); if(File == INVALID_HANDLE_VALUE) { iRet=6 ; } } if(iRet==0) { Written=0; if(WriteFile(File,pData,dwSize,&Written,0)==NULL) { iRet=7; } } CloseHandle(File); FreeLibrary(hExe); hb_retni(iRet); }



полная версия страницы