home *** CD-ROM | disk | FTP | other *** search
- /*
- **
- ** InputStreamC.cpp
- **
- ** $VER: InputStreamC.cpp 1.4 (17.06.99)
- **
- ** $Revision: 1.3 $
- ** $State: Exp $
- ** $Date: 1998/08/16 19:03:37 $
- **
- */
-
-
- //----------------------------------------------------------------------------------------------------
-
- /// Includes
-
- #ifndef _INCLUDE_STDLIB_H
- #include <stdlib.h>
- #endif
-
- #ifndef _INCLUDE_MATH_H
- #include <math.h>
- #endif
-
- #ifndef CLIB_DOS_PROTOS_H
- #include <clib/dos_protos.h>
- #endif
-
- #ifndef _PEGASE_HPP
- #include "Pegase.hpp"
- #endif
-
- #ifndef _INPUTSTREAM_CLASS_HPP
- #include "InputStreamC.hpp"
- #endif
-
- #ifndef _MEMORY_HPP
- #include "Memory.hpp"
- #endif
-
- ///
-
-
- // Fonctions permettant de convertir des données au format Intel vers le format Motorola (et inversement)
-
- inline WORD _getword(WORD w)
- {
- return ( (w >> 8) + (w * 256) );
- }
-
- inline LONG _getlong(LONG l)
- {
- return ( ((l & 0xFF000000) >> 24) + ((l & 0x00FF0000) >> 8) + ((l & 0x0000FF00) * 256) + ((l & 0x000000FF) << 24) );
- }
-
-
- //----------------------------------------------------------------------------------------------------
-
- // La fonction Seek() ne fonctionne pas correctement avec le FileSystem v36/37.
- // Voir les Autodocs pour le détail.
-
- LONG NewSeek(BPTR file, LONG position, LONG offset)
- {
- LONG p = ::Seek(file, position, offset);
- if (IoErr()) p = -1;
- return p;
- }
-
-
- //----------------------------------------------------------------------------------------------------
- //======================================= Classe InputStreamC ========================================
- //----------------------------------------------------------------------------------------------------
-
- /// InputStreamC::AllocStreamBuffer()
- /****** Class InputStreamC/AllocStreamBuffer ********************************
- *
- * NAME
- * InputStreamC::AllocStreamBuffer -- Allouer le tampon de lecture.
- *
- * SYNOPSIS
- * ErrorCode = InputStreamC::AllocStreamBuffer()
- *
- * e_IoErrors InputStreamC::AllocStreamBuffer();
- *
- * FUNCTION
- * Alloue le tampon de lecture pour le flux d'entrée. Ce tampon est aligné
- * sur une frontière de page particulière, permettant ainsi certaines opti-
- * misations suivant le CPU utilisé.
- *
- * La taille du tampon est fixe, déterminée à la compilation. C'est un mul-
- * tiple entier de la taille de chaque page attendue par l'encodeur.
- *
- * RESULT
- * ErrorCode - IOERR_NONE ou IOERR_NO_MEMORY;
- *
- * NOTES
- * Plusieurs fonctions assument que la taille du tampon de lecture est un
- * multiple de la taille de chaque page attendue par l'encodeur.
- *
- * SEE ALSO
- * InputStreamC::FreeStreamBuffer()
- *
- *****************************************************************************
- *
- */
-
-
- e_IoErrors InputStreamC::AllocStreamBuffer()
- {
- const ULONG iBufferSize = INPUT_BUFF_SIZE + (istr_iRollGap * 2);
-
- if ( (istr_pBufferAddr = (WORD *) AllocAlignedBuffer(iBufferSize)) )
- {
- istr_iBufferSize = INPUT_BUFF_SIZE;
- istr_pBufferAddr += istr_iRollGap;
- istr_pCurrentPos = istr_pUpperLimit = istr_pBufferAddr + (istr_iBufferSize >> 1);
- return IOERR_NONE;
- }
-
- SetIoError(IOERR_NO_MEMORY);
- return IOERR_NO_MEMORY;
- }
- ///
- /// InputStreamC::FreeStreamBuffer()
- /****** Class InputStreamC/FreeStreamBuffer *********************************
- *
- * NAME
- * InputStreamC::FreeStreamBuffer -- Libérer le tampon de lecture.
- *
- * SYNOPSIS
- * InputStreamC::FreeStreamBuffer()
- *
- * void InputStreamC::FreeStreamBuffer();
- *
- * FUNCTION
- * Libère le tampon de lecture utilisé par le flux d'entrée (à condition
- * qu'il ait été effectivement alloué).
- *
- * SEE ALSO
- * InputStreamC::AllocStreamBuffer()
- *
- *****************************************************************************
- *
- */
-
-
- void InputStreamC::FreeStreamBuffer()
- {
- if (istr_pBufferAddr)
- {
- FreeAlignedBuffer(istr_pBufferAddr - istr_iRollGap);
- istr_pBufferAddr = NULL;
- }
- }
- ///
- /// InputStreamC::RollBuffer()
- /****** Class InputStreamC/RollBuffer ***************************************
- *
- * NAME
- * InputStreamC::RollBuffer -- "Enrouler le tampon de lecture"
- *
- * SYNOPSIS
- * InputStreamC::RollBuffer()
- *
- * void InputStreamC::RollBuffer();
- *
- * FUNCTION
- * Recopie les dernières données du tampon dans la partie réservée en tête
- * de celui-ci. La taille du bloc transferé correspond à la taille du bloc
- * d'entête.
- *
- *****************************************************************************
- *
- */
-
-
- void InputStreamC::RollBuffer()
- {
- if (istr_iRollGap)
- {
- ULONG gap = istr_iRollGap;
- ULONG *dst = (ULONG *) (istr_pBufferAddr - gap);
- ULONG *src = dst + (istr_iBufferSize >> 2);
-
- for (; gap > 0; gap--)
- *dst++ = *src++;
- }
- }
- ///
- /// InputStreamC::OpenStream()
- /****** Class InputStreamC/OpenStream ***************************************
- *
- * NAME
- * InputStreamC::OpenStream -- Ouvre le fichier à encoder.
- *
- * SYNOPSIS
- * ErrorCode = InputStreamC::OpenStream()
- *
- * e_IoErrors InputStreamC::OpenStream();
- *
- * FUNCTION
- * Ouvre le fichier à encoder en lecture.
- *
- * RESULT
- * ErrorCode - Code d'erreur (IOERR_#?)
- *
- * NOTES
- * Fonction virtuelle.
- *
- * SEE ALSO
- * IFF_AudioC::OpenStream()
- * InputStreamC::CloseStream()
- *
- *****************************************************************************
- *
- */
-
-
- e_IoErrors InputStreamC::OpenStream()
- {
- e_IoErrors IOErr = IOERR_NONE;
- istr_wEOF = istr_wContinue = FALSE;
-
- // Ouvrir le fichier audio. On change de répertoire pour s'assurer qu'on adresse
- // bien le bon fichier.
- // istr_iIoError reçoit une copie du code d'erreur du DOS après chaque opération de
- // façon à pouvoir contrôler que l'objet a été crée correctement.
- // Par la même occasion, istr_bpFileHandle reste NULL si le fichier n'a pas pu être
- // ouvert.
-
- if ( (istr_bpNewDirLock = ::Lock((STRPTR) GetPathName(), ACCESS_READ)) )
- {
- istr_bpOldDirLock = ::CurrentDir(istr_bpNewDirLock);
-
- if ( (istr_bpFileHandle = ::Open((STRPTR) GetFileName(), MODE_OLDFILE)) == 0)
- IOErr = IOERR_OPEN;
- }
- else IOErr = IOERR_DOS;
-
- SetIoError(IOErr, IoErr());
-
- return IOErr;
- }
- ///
- /// InputStreamC::CloseStream()
- /****** Class InputStreamC/CloseStream **************************************
- *
- * NAME
- * InputStreamC::CloseStream -- Ferme le fichier à encoder.
- *
- * SYNOPSIS
- * InputStreamC::CloseStream()
- *
- * void InputStreamC::CloseStream();
- *
- * FUNCTION
- * Ferme le fichier à encoder. Cette fonction peut être appelée même si le
- * fichier a déjà été fermé, ou lorsqu'il n'a pas été ouvert.
- *
- * NOTES
- * Fonction virtuelle
- *
- * SEE ALSO
- * IFF_AudioC::CloseStream()
- * InputStreamC::OpenStream()
- *
- *****************************************************************************
- *
- */
-
-
- void InputStreamC::CloseStream()
- {
- if (istr_bpFileHandle)
- {
- ::Close(istr_bpFileHandle);
- istr_bpFileHandle = NULL;
- }
-
- if (istr_bpNewDirLock)
- {
- ::CurrentDir(istr_bpOldDirLock);
- ::UnLock(istr_bpNewDirLock);
- istr_bpOldDirLock = istr_bpNewDirLock = 0;
- }
- }
- ///
- /// InputStreamC::SeekToAudio()
- /****** Class InputStreamC/SeekToAudio **************************************
- *
- * NAME
- * InputStreamC::SeekToAudio -- Préparer la lecture du bloc audio.
- *
- * SYNOPSIS
- * Result = InputStreamC::SeekToAudio()
- *
- * bool InputStreamC::SeekToAudio();
- *
- * FUNCTION
- * Positionne le pointeur de lecture au début du bloc de données audio.
- * Le fichier doit avoir été ouvert au préalable !
- *
- * RESULT
- * Result - FALSE en cas d'erreur.
- *
- * NOTES
- * Fonction virtuelle.
- *
- * SEE ALSO
- * IFF_AudioC::SeekToAudio()
- * WAV_AudioC::SeekToAudio()
- *
- *****************************************************************************
- *
- */
-
-
- int InputStreamC::SeekToAudio()
- {
- /*
- if (NewSeek(istr_bpFileHandle, 0L, OFFSET_BEGINING) >= 0) return TRUE;
-
- return FALSE;
- */
- return TRUE;
- }
- ///
- /// InputStreamC::FillBuffer()
- /****** Class InputStreamC/FillBuffer ***************************************
- *
- * NAME
- * InputStreamC::FillBuffer -- Remplir le tampon de lecture.
- *
- * SYNOPSIS
- * BytesRead = InputStreamC::FillBuffer()
- *
- * LONG InputStreamC::FillBuffer();
- *
- * FUNCTION
- * Remplis le tampon de lecture avec de nouveaux échantillons.
- *
- * RESULT
- * BytesRead - Nombre d'octets lus, ZERO si la fin du fichier a été rencon-
- * trée, ou -1 en cas d'erreur.
- *
- * Le fichier doit avoir été ouvert au préalable, et le tampon de lecture
- * doit avoir été alloué. Aucune vérification n'est effectuée sur ces deux
- * conditions !
- *
- * NOTES
- * Fonction virtuelle
- *
- * SEE ALSO
- * IFF_AudioC::FillBuffer()
- *
- *****************************************************************************
- *
- */
-
-
- LONG InputStreamC::FillBuffer()
- {
- RollBuffer();
- return Read(istr_bpFileHandle, istr_pBufferAddr, istr_iBufferSize);
- }
- ///
- /// InputStreamC::ReadSamples()
- /****** Class InputStreamC/ReadSamples **************************************
- *
- * NAME
- * InputStreamC::ReadSamples -- Obtenir le bloc suivant.
- *
- * SYNOPSIS
- * BlockAddr = InputStreamC::ReadSamples(iNumSamples)
- *
- * WORD * InputStreamC::ReadSamples(UWORD);
- *
- * FUNCTION
- * Retourne un pointeur vers le bloc d'échantillons suivant, ou NULL en cas
- * d'erreur (problème de lecture, ou fin de fichier atteinte).
- * La fonction s'occupe du remplissage du tampon lorsque c'est nécessaire,
- * à moins que la fin du fichier n'ait été atteinte.
- *
- * Le flux d'entrée doit avoir été ouvert au préalable, et la tampon doit
- * avoir été alloué. Aucun contrôle n'est fait concernant ces conditions !
- *
- * INPUTS
- * iNumSamples - Nombre d'échantillons à lire.
- *
- * RESULT
- * BlockAddr - Adresse du prochain bloc, ou NULL. GetIoError() renseigne sur
- * le code d'erreur lorsque le pointeur retourné vaut NULL.
- * Le couple IOERR_WARN + ERROR_NO_MORE_ENTRIES indique que l'on a rencontré
- * la fin du fichier.
- *
- * NOTES
- * Cette fonction repose sur le fait que la taille du tampon est un multiple
- * entier de toutes les tailles de bloc possibles. Voir AllocStreamBuffer().
- *
- *****************************************************************************
- *
- */
-
-
- WORD *InputStreamC::ReadSamples(UWORD iNumSamples)
- {
- if (!istr_wEOF)
- {
- if (istr_iSamplesRead == 0)
- {
- // Le tampon est vide...
-
- if (!istr_wContinue)
- {
- // Procéder au premier remplissage du tampon.
-
- if (!SeekToAudio()) goto Abort;
-
- istr_wContinue = TRUE;
- }
-
- // Remplir le tampon avec les échantillons suivant.
-
- istr_iSamplesRead = FillBuffer();
-
- if (istr_iSamplesRead < 0) goto Abort;
- if (istr_iSamplesRead == 0)
- {
- SetIoError(IOERR_WARN, ERROR_NO_MORE_ENTRIES);
- istr_wEOF = TRUE; // Fin de fichier atteinte.
- goto Exit_;
- }
- istr_iSamplesRead >>= 1; // 16 bits par échantillon.
- }
- return GetNextBlockAddr(iNumSamples);
- }
-
- Abort:
- SetIoError(IOERR_DOS, ::IoErr());
-
- Exit_:
- return NULL;
- }
- ///
- /// InputStreamC::GetNextBlockAddr()
- /****** InputStreamC/GetNextBlockAddr ***************************************
- *
- * NAME
- * GetNextBlockAddr -- Obtenir l'adresse du prochain bloc (Privée).
- *
- * SYNOPSIS
- * NextBlock = GetNextBlockAddr(iNumSamples)
- *
- * WORD *GetNextBlockAddr(UWORD);
- *
- * FUNCTION
- * Mets à jour les membres privés en rapport avec la gestion du tampon d'
- * entrée.
- * Lorsque le tampon vient d'être rempli pour la première fois, ou lorque l'
- * adresse du prochain bloc serait hors du tampon, le prochain bloc se situe
- * alors en début de tampon.
- * Si le bloc courant ne contient pas assez d'échantillons, il est completé
- * avec des 0.
- *
- * Le nombre d'échantillons traités est mis à jour par cette fonction.
- *
- * INPUTS
- * iNumSamples - Nombre d'échantillons.
- *
- * RESULT
- * NextBlock - Pointeur vers le bloc de données à traiter.
- *
- * NOTES
- * Cette fonction repose sur le fait que la taille du tampon d'entrée est un
- * multiple entier de toutes les tailles de bloc possibles.
- * void AllocStreamBuffer()
- *
- *****************************************************************************
- *
- */
-
-
- WORD *InputStreamC::GetNextBlockAddr(UWORD iNumSamples)
- {
- istr_pCurrentPos += iNumSamples;
-
- if (istr_pCurrentPos >= istr_pUpperLimit)
- {
- istr_pCurrentPos = istr_pBufferAddr; // Réinitialiser le pointeur courant en début de bloc
- } // si le dernier bloc du tampon a été traité.
-
- istr_iSmplProcessed += (iNumSamples > istr_iSamplesRead) ? istr_iSamplesRead : iNumSamples;
-
- // Recalculer le facteur de progression si nécessaire.
-
- if (istr_roFileInfo.GetNumSamples() && istr_iSmplProcessed >= istr_iNextLimit)
- {
- istr_iProgressValue = istr_iSmplProcessed * 100 / istr_roFileInfo.GetNumSamples();
- istr_iNextLimit += istr_iStepMin;
- }
-
- // Compléter le bloc s'il est trop court.
-
- WORD *p = istr_pBufferAddr + istr_iSamplesRead;
-
- for (; istr_iSamplesRead < iNumSamples; istr_iSamplesRead++)
- *p++ = 0;
-
- istr_iSamplesRead -= iNumSamples;
-
- return istr_pCurrentPos;
- }
- ///
-
- //----------------------------------------------------------------------------------------------------
- //======================================== Classe RAW_AudioC =========================================
- //----------------------------------------------------------------------------------------------------
- //
- // Fonctions spécialisées dans la gestion des fichiers RAW/PCM
-
- /// RAW_AudioC/GetFileInfos()
- /****** Class RAW_AudioC/GetFileInfos ***************************************
- *
- * NAME
- * RAW_AudioC::GetFileInfos -- Analyse un fichier RAW/PCM
- *
- * SYNOPSIS
- * Result = RAW_AudioC::GetFileInfos()
- *
- * bool RAW_AudioC::GetFileInfos();
- *
- * FUNCTION
- * Analyse le fichier afin de connaître le nombre d'échantillons.
- *
- * RESULT
- * Result - FALSE en cas d'erreur.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle
- *
- * - Le nombre d'échantillons est déterminé par la taille du fichier.
- * - Les échantillons sont considérés comme étant codés sur 16 bits et au
- * format Motorola.
- * - Le fichier audio est considéré comme étant en mono.
- * - La fréquence d'échantillonage est indéterminée.
- *
- * SEE ALSO
- * AIFF_AudioC::GetFileInfos()
- * MAUD_AudioC::GetFileInfos()
- * CDDA_AudioC::GetFileInfos()
- * WAV_AudioC::GetFileInfos()
- *
- *****************************************************************************
- *
- */
-
-
- int RAW_AudioC::GetFileInfos()
- {
- int success;
- ULONG NumFrames = istr_roFileInfo.GetFileLength() >> 1;
-
- SetNumFrames(NumFrames);
- if ( !(success = istr_roFileInfo.OverrideSettings(0, 1) )) // Mode mono.
- SetIoError(IOERR_INTERNAL, ERROR_OBJECT_WRONG_TYPE);
-
- istr_roFileInfo.SetEncodingMode(MONO);
- SetAudioFormat(FORMAT_MOTOROLA_MONO);
-
- return success;
- }
- ///
- /// RAW_AudioC/OverrideSettings()
- /****** Class RAW_AudioC/OverrideSettings ***********************************
- *
- * NAME
- * RAW_AudioC::OverrideSettings -- Modifier les réglages du fichier.
- *
- * SYNOPSIS
- * Result = RAW_AudioC::OverrideSettings(iSampleFreq, bChannels)
- *
- * bool RAW_AudioC::OverrideSettings(ULONG, UBYTE);
- *
- * FUNCTION
- * Modifie la fréquence d'échantillonage du fichier audio.
- * Puisque les fichiers RAW/PCM sont censés être en mono, le nombre de
- * canaux spécifié est ignoré (toujours 1).
- *
- * INPUTS
- * iSampleFreq - Fréquence d'échantillonage (Hz).
- * bChannels - IGNORE
- *
- * RESULT
- * Result - FALSE en cas d'erreur.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle.
- *
- * Un fichier RAW/PCM est supposé toujours être en mono.
- *
- * SEE ALSO
- * CDDA_AudioC::GetFileInfos()
- * IFF_AudioC::GetFileInfos()
- * WAV_AudioC::GetFileInfos()
- *
- *****************************************************************************
- *
- */
-
-
- int RAW_AudioC::OverrideSettings(ULONG iSampleFreq, UBYTE bChannels)
- {
- return istr_roFileInfo.OverrideSettings(iSampleFreq, 1);
- }
- ///
-
- //----------------------------------------------------------------------------------------------------
- //======================================== Classe IFF_AudioC =========================================
- //----------------------------------------------------------------------------------------------------
- //
- // Fonctions de base pour la gestion des fichiers IFF.
-
- /// IFF_AudioC::OpenStream()
- /****** Class IFF_AudioC/OpenStream *****************************************
- *
- * NAME
- * IFF_AudioC::OpenStream -- Ouvrir le flux IFF en lecture.
- *
- * SYNOPSIS
- * Error = IFF_AudioC::OpenStream()
- *
- * e_IoErrors IFF_AudioC::OpenStream();
- *
- * FUNCTION
- * Initialise et ouvre en lecture un flux IFF.
- *
- * RESULT
- * Error - Code d'erreur (IOERR_#?).
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle
- *
- * SEE ALSO
- * InputStreamC::OpenStream()
- * IFF_AudioC::CloseStream()
- *
- *****************************************************************************
- *
- */
-
-
- e_IoErrors IFF_AudioC::OpenStream()
- {
- e_IoErrors IOErr = IOERR_NONE;
- LONG i2ndError = 0;
-
- // Ouvrir le fichier audio.
-
- if ( (IOErr = InputStreamC::OpenStream()) != IOERR_NONE) return IOErr;
-
- // Ouvrir le flux IFF.
-
- if ( (istr_pIFF = AllocIFF()) )
- {
- istr_pIFF->iff_Stream = istr_bpFileHandle;
- ::InitIFFasDOS(istr_pIFF);
- if ( (i2ndError = ::OpenIFF(istr_pIFF, IFFF_READ)) == 0) return IOERR_NONE;
-
- // Erreur pendant l'ouverture : Libérer les ressources allouées partiellement.
-
- ::FreeIFF(istr_pIFF);
- istr_pIFF = NULL;
- }
- else i2ndError = IFFERR_NOMEM;
-
- SetIoError(IOERR_IFF, i2ndError);
- return IOERR_IFF;
- }
- ///
- /// IFF_AudioC::CloseStream()
- /****** Class IFF_AudioC/CloseStream ****************************************
- *
- * NAME
- * IFF_AudioC::CloseStream -- Ferme un flux IFF
- *
- * SYNOPSIS
- * IFF_AudioC::CloseStream()
- *
- * void IFF_AudioC::CloseStream();
- *
- * FUNCTION
- * Ferme et libère un flux IFF. Cette fonction peut être appelée même si le
- * flux IFF est déjà fermé ou lorsqu'il n'a pas été ouvert.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle
- *
- * SEE ALSO
- * InputStreamC::CloseStream()
- * IFF_AudioC::OpenStream()
- *
- *****************************************************************************
- *
- */
-
-
- void IFF_AudioC::CloseStream()
- {
- // Fermer le flux IFF
-
- if (istr_pIFF)
- {
- ::CloseIFF(istr_pIFF);
- ::FreeIFF(istr_pIFF);
- istr_pIFF = 0;
- }
-
- // Fermer le fichier audio.
-
- InputStreamC::CloseStream();
- }
- ///
- /// IFF_AudioC::SeekToAudio()
- /****** Class IFF_AudioC/SeekToAudio ****************************************
- *
- * NAME
- * IFF_AudioC::SeekToAudio -- Préparer la lecture du bloc audio.
- *
- * SYNOPSIS
- * Result = IFF_AudioC::SeekToAudio()
- *
- * bool IFF_AudioC::SeekToAudio();
- *
- * FUNCTION
- * Positionne le pointeur de lecture au début du bloc de données audio.
- * Le flux IFF doit avoir été ouvert et initialisé avant d'appeler cette
- * fonction.
- *
- * RESULT
- * Result - FALSE en cas d'erreur.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle.
- *
- * SEE ALSO
- * InputStreamC::SeekToAudio()
- * WAV_AudioC::SeekToAudio()
- *
- *****************************************************************************
- *
- * Le format du chunk audio varie d'un type de fichier à l'autre. De fait,
- * la fonction est capable de sauter les informations situées en début de
- * chunk, et précédant les données audio attendues.
- * A l'heure actuelle, les fichier MAUD ne possèdent aucune données en
- * entête, alors que les fichiers AIFF contiennent une structure de 8 octets
- * juste avant les données audio.
- *
- */
-
-
- int IFF_AudioC::SeekToAudio()
- {
- const ULONG iBufferSize = sizeof(struct AIFF_SSND); // Pour l'instant, cela correspond au maximum possible,
- // à savoir la taille de la structure AIFF_SSND.
-
- ContextNode *pCNode;
- LONG i2ndError = 0;
- char a_TempBuff[iBufferSize];
-
- if ( (i2ndError = ::StopChunk(istr_pIFF, istr_iTypeChunkID, istr_iDataChunkID)) == 0
- && (i2ndError = ::ParseIFF(istr_pIFF, IFFPARSE_SCAN)) == 0)
- {
- pCNode = ::CurrentChunk(istr_pIFF);
-
- // S'il faut sauter des données au début du chunk, c'est le moment de le faire...
-
- for (LONG i = istr_iAudioDataOffset; i > 0 && i2ndError > 0; i -= iBufferSize)
- i2ndError = ::ReadChunkBytes(istr_pIFF, a_TempBuff, iBufferSize);
-
- if (i2ndError == 0) return TRUE;
- }
-
- // Placer les codes d'erreur.
-
- SetIoError(IOERR_IFF, i2ndError);
- return FALSE;
- }
- ///
- /// IFF_AudioC::FillBuffer()
- /****** Class IFF_AudioC/FillBuffer *****************************************
- *
- * NAME
- * IFF_AudioC::FillBuffer -- Remplir le tampon de lecture.
- *
- * SYNOPSIS
- * BytesRead = IFF_AudioC::FillBuffer()
- *
- * LONG IFF_AudioC::FillBuffer();
- *
- * FUNCTION
- * Remplis le tampon de lecture avec de nouveaux échantillons.
- *
- * RESULT
- * BytesRead - Nombre d'octets lus, ZERO si la fin du fichier a été rencon-
- * trée, ou -1 en cas d'erreur.
- *
- * Le fichier doit avoir été ouvert au préalable, et le tampon de lecture
- * doit avoir été alloué. Aucune vérification n'est effectuée sur ces deux
- * conditions !
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle
- *
- * SEE ALSO
- * InputStreamC::FillBuffer()
- *
- *****************************************************************************
- *
- */
-
-
- LONG IFF_AudioC::FillBuffer()
- {
- RollBuffer();
- return ::ReadChunkBytes(istr_pIFF, istr_pBufferAddr, istr_iBufferSize);
- }
- ///
- /// IFF_AudioC::ReadChunks()
- /****** Class IFF_AudioC/ReadChunks *****************************************
- *
- * NAME
- * IFF_AudioC::ReadChunks -- Lire le contenu d'un chunk précis.
- *
- * SYNOPSIS
- * Datas = IFF_AudioC::ReadChunks()
- *
- * StoredProperty * IFF_AudioC::ReadChunks();
- *
- * FUNCTION
- * Recherche et charge les chunks du fichier IFF.
- * Actuellement, la fonction effectue une copie du bloc d'entête du fichier
- * IFF, et positionne le contexte sur le bloc de données audio.
- *
- * RESULT
- * Datas - Pointeur vers la structure StoredProperty décrivant le bloc d'
- * entête, ou NULL en cas d'erreur.
- *
- * NOTES
- * Le fichier IFF doit avoir été ouvert au préalable.
- *
- *****************************************************************************
- *
- */
-
-
- StoredProperty *IFF_AudioC::ReadChunks()
- {
- LONG i2ndError = 0;
-
- if ( (i2ndError = ::PropChunk(istr_pIFF, istr_iTypeChunkID, istr_iHeaderChunkID)) == 0
- && (i2ndError = ::StopChunk(istr_pIFF,istr_iTypeChunkID, istr_iDataChunkID)) == 0
- && (i2ndError = ::ParseIFF(istr_pIFF, IFFPARSE_SCAN) == 0))
- {
- return ::FindProp(istr_pIFF, istr_iTypeChunkID, istr_iHeaderChunkID);
- }
-
- // Mémoriser les codes d'erreur.
-
- SetIoError(IOERR_IFF, i2ndError);
- return NULL;
- }
- ///
- /// IFF_AudioC::CheckAudioChunk()
- /****** Class IFF_AudioC/CheckAudioChunk ************************************
- *
- * NAME
- * IFF_AudioC::CheckAudioChunk -- Contrôler la taille du chunk audio.
- *
- * SYNOPSIS
- * IFF_AudioC::CheckAudioChunk(iOffset)
- *
- * void IFF_AudioC::CheckAudioChunk(ULONG);
- *
- * FUNCTION
- * Recherche le chunk audio associé au fichier IFF courant afin de contrôler
- * sa taille par rapport au nombre d'échantillons spécifiés dans l'entête.
- *
- * Si la taille ne correspond pas, le code d'erreur IOERR_WARN associé à
- * ERROR_BAD_HUNK est placé.
- *
- * INPUT
- * iOffset - Nombre d'octets à sauter en début de chunk pour adresser les
- * échantillons.
- *
- * NOTES
- * Le fichier IFF doit avoir été ouvert au préalable.
- *
- *****************************************************************************
- *
- */
-
-
- void IFF_AudioC::CheckAudioChunk(ULONG iOffset)
- {
- ContextNode *pCNode;
- ULONG iSize;
-
- pCNode = ::CurrentChunk(istr_pIFF);
- iSize = (pCNode->cn_Size - iOffset) >> 1; // 16 bits par échantillons.
-
- if ( iSize != GetNumSamples() )
- {
- SetNumFrames( (GetNumChannels() == 1) ? iSize : iSize >> 1);
- SetIoError(IOERR_WARN, ERROR_BAD_HUNK);
- }
- }
- ///
-
- //----------------------------------------------------------------------------------------------------
- //======================================== Classe AIFF_AudioC ========================================
- //----------------------------------------------------------------------------------------------------
- //
- // Fonctions spécialisées dans la gestion des fichiers AIFF.
-
- /// AIFF_AudioC::GetFileInfos()
- /****** Class AIFF_AudioC/GetFileInfos **************************************
- *
- * NAME
- * AIFF_AudioC::GetFileInfos -- Analyse un fichier AIFF.
- *
- * SYNOPSIS
- * Result = AIFF_AudioC::GetFileInfos()
- *
- * bool AIFF_AudioC::GetFileInfos();
- *
- * FUNCTION
- * Analyse le fichier AIFF afin de connaître ses réglages particuliers, tels
- * que le nombre de canaux, le nombre d'échantillons, la fréquence d'échan-
- * tillonage, etc.
- *
- * La fonction vérifie aussi que la taille du chunk audio est en accord avec
- * le nombre d'échantillons annoncé dans l'entête du fichier.
- *
- * RESULT
- * Result - TRUE si les paramètres du fichier ont été lus, FALSE en cas d'
- * erreur. GetIoError() permet de récupérer, dans ce dernier cas, un code
- * d'erreur plus précis.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle.
- *
- * La fréquence d'échantillonage est obtenue avec une fonction simplifiée
- * basée sur le format d'un nombre flottant (IEEE-754).
- * Si le fichier AIFF n'est pas un fichier audio, ou si les échantillons ne
- * sont pas codés sur 16 bits, ou si le nombre de canaux est supérieur à 2,
- * alors le fichier AIFF est rejeté.
- *
- * SEE ALSO
- * MAUD_AudioC::GetFileInfos()
- * CDDA_AudioC::GetFileInfos()
- * RAW_AudioC::GetFileInfos()
- * WAV_AudioC::GetFileInfos()
- *
- *****************************************************************************
- *
- * AIFF : COMM = Chunk de description (obligatoire et unique).
- * SSND = Chunk des données audio (unique).
- *
- */
-
-
- int AIFF_AudioC::GetFileInfos()
- {
-
- // Structure des chunks AIFF.
-
- struct IEEE_754 {short exponent;
- long mantissa_hi;
- ULONG mantissa_lo;
- };
-
- struct AIFF_COMM {short NumChannels; // Nombre de canaux (1, 2, 4, etc)
- ULONG NumSampleFrames; // Nombre d'échantillons par canal.
- short SampleSize; // Nombre de bits par échantillons.
- IEEE_754 SampleRate; // Fréquence d'échantillonage.
- };
-
- int success = FALSE;
-
- if (OpenStream() == IOERR_NONE)
- {
- StoredProperty *pSP;
-
- // Décoder le chunk principal.
-
- if ( (pSP = ReadChunks()) )
- {
- AIFF_COMM *pCOMM = (AIFF_COMM *) pSP->sp_Data;
-
- //-----------------------------------------------------------------
-
- if (pCOMM->SampleSize == 16 && pCOMM->NumSampleFrames != 0L)
- {
- // Décoder le format IEEE_754;
- // On utilise les hypothèses suivantes :
- // - La fréquence d'échantillonage est positive.
- // - Elle est définie par un nombre entier.
-
- WORD e = (pCOMM->SampleRate.exponent & 0x7FFF) - 16383;
- ULONG smplfreq = pCOMM->SampleRate.mantissa_hi;
-
- if (e > 0 && e < 30 && pCOMM->NumChannels < 3)
- {
- smplfreq = (((smplfreq >> (30-e)) + 1 ) >> 1);
- SetNumFrames(pCOMM->NumSampleFrames);
-
- if ( !(success = istr_roFileInfo.OverrideSettings(smplfreq, pCOMM->NumChannels)) )
- SetIoError(IOERR_INTERNAL, ERROR_OBJECT_WRONG_TYPE);
-
- SetAudioFormat( (pCOMM->NumChannels == 1) ? FORMAT_MOTOROLA_MONO : FORMAT_MOTOROLA_STEREO );
-
- CheckAudioChunk(sizeof(struct AIFF_SSND));
- CloseStream();
- return success;
- }
- }
- }
- // Fichier AIFF non supporté.
-
- SetFileType(AFT_BAD_AIFF);
- SetIoError(IOERR_INTERNAL, ERROR_OBJECT_WRONG_TYPE);
- CloseStream();
- }
-
- return success;
- }
- ///
-
- //----------------------------------------------------------------------------------------------------
- //======================================== Classe MAUD_AudioC ========================================
- //----------------------------------------------------------------------------------------------------
- //
- // Fonctions spécialisées dans la gestion des fichiers MAUD.
-
- /// Définitions
- #define ID_MAUD 0x4D415544 /* 'MAUD' */ /* the FORM-ID */
- #define ID_MHDR 0x4D484452 /* 'MHDR' */ /* file header chunk */
- #define ID_MDAT 0x4D444154 /* 'MDAT' */ /* sample data chunk */
- #define ID_MINF 0x4D494E46 /* 'MINF' */ /* optional channel info chunk (future) */
-
- /* ---- the file header 'MHDR' */
-
- struct MaudHeader {
- ULONG mhdr_Samples; /* number of samples stored in MDAT */
- UWORD mhdr_SampleSizeC; /* number of bits per sample as stored in MDAT */
- UWORD mhdr_SampleSizeU; /* number of bits per sample after decompression */
- ULONG mhdr_RateSource; /* clock source frequency (see maud.doc) */
- UWORD mhdr_RateDevide; /* clock devide (see maud.doc) */
- UWORD mhdr_ChannelInfo; /* channel information (see below) */
- UWORD mhdr_Channels; /* number of channels (mono: 1, stereo: 2, ...) */
- UWORD mhdr_Compression; /* compression type (see below) */
- ULONG mhdr_Reserved1; /* MUST be set to 0 when saving */
- ULONG mhdr_Reserved2; /* MUST be set to 0 when saving */
- ULONG mhdr_Reserved3; /* MUST be set to 0 when saving */
- };
-
- /* ---- possible values for mhdr_ChannelInfo */
-
- #define MCI_MONO 0 /* mono */
- #define MCI_STEREO 1 /* stereo */
- #define MCI_MULTIMONO 2 /* mono multichannel (channels can be 2, 3, 4, ...) */
- #define MCI_MULTISTEREO 3 /* stereo multichannel (channels must be 4, 6, 8, ...) */
- #define MCI_MULTICHANNEL 4 /* multichannel (requires additional MINF-chunks) (future) */
-
- /* ---- possible values for mhdr_Compression */
-
- #define MCOMP_NONE 0 /* no compression */
- #define MCOMP_FIBDELTA 1 /* 'Fibonacci Delta Compression' as used in 8SVX */
- #define MCOMP_ALAW 2 /* 16->8 bit, European PCM standard A-Law */
- #define MCOMP_ULAW 3 /* 16->8 bit, American PCM standard µ-Law */
- #define MCOMP_ADPCM2 4 /* 16->2 bit, ADPCM compression */
- #define MCOMP_ADPCM3 5 /* 16->3 bit, ADPCM compression */
- #define MCOMP_ADPCM4 6 /* 16->4 bit, ADPCM compression */
- #define MCOMP_ADPCM5 7 /* 16->5 bit, ADPCM compression */
- #define MCOMP_LONGDAT 8 /* 16->12 bit, used for DAT-longplay */
- ///
-
- /// MAUD_AudioC::GetFileInfos()
- /****** Class MAUD_AudioC/GetFileInfos **************************************
- *
- * NAME
- * MAUD_AudioC::GetFileInfos -- Analyse un fichier MAUD.
- *
- * SYNOPSIS
- * Result = MAUD_AudioC::GetFileInfos()
- *
- * bool MAUD_AudioC::GetFileInfos();
- *
- * FUNCTION
- * Analyse le fichier MAUD afin de connaître ses réglages particuliers, tels
- * que le nombre de canaux, le nombre d'échantillons, la fréquence d'échan-
- * tillonage, etc.
- *
- * RESULT
- * Result - TRUE si les paramètres du fichier ont été lus, FALSE en cas d'
- * erreur. GetIoError() permet de récupérer, dans ce dernier cas, un code
- * d'erreur plus précis.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle
- *
- * Pour que le fichier MAUD soit accepté, il faut que les échantillons
- * soient codés sur 16 bits, qu'il y ait 1 ou 2 canaux audio, et que les
- * échantillons ne soient pas compressés.
- *
- * SEE ALSO
- * AIFF_AudioC::GetFileInfos()
- * CDDA_AudioC::GetFileInfos()
- * RAW_AudioC::GetFileInfos()
- * WAV_AudioC::GetFileInfos()
- *
- *****************************************************************************
- *
- * MAUD : MHDR = Chunk de description (obligatoire et unique).
- * MDAT = Chunk des données audio (unique).
- *
- */
-
-
- int MAUD_AudioC::GetFileInfos()
- {
- int success = FALSE;
-
- if (OpenStream() == IOERR_NONE)
- {
- StoredProperty *pSP;
-
- // Décoder le chunk principal.
-
- if ( (pSP = ReadChunks()) )
- {
- MaudHeader *pHDR = (MaudHeader *) pSP->sp_Data;
-
- //-----------------------------------------------------------------
-
- // On ne supporte que les fichiers MAUD 16 bits (sans compression).
-
- if (pHDR->mhdr_SampleSizeC == 16 && pHDR->mhdr_Compression == MCOMP_NONE)
- {
- ULONG smplfreq = pHDR->mhdr_RateSource / pHDR->mhdr_RateDevide;
-
- if (pHDR->mhdr_ChannelInfo == MCI_MONO || pHDR->mhdr_ChannelInfo == MCI_STEREO)
- {
- SetNumFrames(pHDR->mhdr_Samples);
- success = istr_roFileInfo.OverrideSettings(smplfreq, pHDR->mhdr_Channels);
- SetAudioFormat( (pHDR->mhdr_Channels == 1) ? FORMAT_MOTOROLA_MONO : FORMAT_MOTOROLA_STEREO );
-
- if (!success) SetIoError(IOERR_INTERNAL, ERROR_OBJECT_WRONG_TYPE);
-
- CheckAudioChunk(0L);
- CloseStream();
- return success;
- }
- }
- }
- // Fichier MAUD non supporté.
-
- SetFileType(AFT_BAD_MAUD);
- SetIoError(IOERR_INTERNAL, ERROR_OBJECT_WRONG_TYPE);
- CloseStream();
- }
-
- return success;
- }
- ///
-
- //----------------------------------------------------------------------------------------------------
- //======================================== Classe CDDA_AudioC ========================================
- //----------------------------------------------------------------------------------------------------
- //
- // Fonctions spécialisées dans la gestion des fichiers CDDA
-
- /// CDDA_AudioC/GetFileInfos()
- /****** Class CDDA_AudioC/GetFileInfos **************************************
- *
- * NAME
- * CDDA_AudioC::GetFileInfos -- Analyse un fichier CDDA
- *
- * SYNOPSIS
- * Result = CDDA_AudioC::GetFileInfos()
- *
- * bool CDDA_AudioC::GetFileInfos();
- *
- * FUNCTION
- * Analyse le fichier afin de connaître le nombre d'échantillons. Ce nombre
- * est basé sur la taille du fichier.
- * La fonction analyse en outre un bloc pris dans le milieu du fichier afin
- * d'essayer de déterminer le format de ce fichier (MOTOROLA/INTEL).
- *
- * RESULT
- * Result - FALSE en cas d'erreur (Erreur de lecture).
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle
- *
- * Les fichiers CDDA sont considérés comme étant en stéréo, avec des échan-
- * tillons codés sur 16 bits, et échantillonnés à 44100 Hz.
- * La discrimination entre les formats Motorola et Intel se base sur un test
- * empirique. Elle repose sur la moyenne des différences entre les échantil-
- * lons d'un bloc pris dans le milieu du fichier. Cette reconnaissance n'est
- * donc pas absolument fiable.
- *
- * SEE ALSO
- * MAUD_AudioC::GetFileInfos()
- * AIFF_AudioC::GetFileInfos()
- * RAW_AudioC::GetFileInfos()
- * WAV_AudioC::GetFileInfos()
- *
- *****************************************************************************
- *
- */
-
-
- int CDDA_AudioC::GetFileInfos()
- {
- const int iNumSmpl = 256*16; // Nombre d'échantillons à examiner.
- const int iThreshold = 10000; // Limite acceptée pour la moyenne. Au delà de cette limite,
- // on formule l'hypothèse que le fichier est au format INTEL.
- ULONG NumFrames = istr_roFileInfo.GetFileLength() >> 2;
-
- SetNumFrames(NumFrames);
-
- istr_roFileInfo.SetEncodingMode(STEREO);
- istr_roFileInfo.OverrideSettings(44100, 2);
-
- int i, sum;
- WORD *pSamples = NULL;
- LONG iRead = 0;
- int iResult = FALSE;
-
- SetAudioFormat(FORMAT_MOTOROLA_STEREO); // Présumer que le fichier est au format Motorola.
-
- if (istr_roFileInfo.GetCDDAFmt() == 1)
- {
- SetFileType(AFT_CDDA);
- iResult = TRUE;
- }
- else if (istr_roFileInfo.GetCDDAFmt() == 2)
- {
- SetAudioFormat(FORMAT_INTEL_STEREO);
- SetFileType(AFT_CDDA_INTEL);
- iResult = TRUE;
- }
- else
- {
- // Ouvrir le fichier, puis charger un petit bloc d'échantillons dans un tampon pour analyse.
-
- if (OpenStream() == IOERR_NONE && (pSamples = new WORD[iNumSmpl * 2]) )
- {
- if (NewSeek(istr_bpFileHandle, NumFrames >> 1, OFFSET_BEGINING) >= 0
- && (iRead = ::Read(istr_bpFileHandle, pSamples, iNumSmpl * 4) >> 1) )
- {
- // Analyser le tampon.
- // On calcule ici la somme des différences entre chaque echantillon.
- // Si la moyenne de ces sommes est inférieure à une certaine limite,
- // on fait l'hypothèse que le fichier est au format Motorola.
-
- for (i = 2, sum = 0; i < iRead; i += 2)
- {
- int t = pSamples[i] - pSamples[i-2];
- sum += (t < 0) ? -t : t;
- }
-
- int analyze = (sum * 2) / iRead;
-
- if (analyze > iThreshold)
- {
- SetFileType(AFT_CDDA_INTEL);
- SetAudioFormat(FORMAT_INTEL_STEREO);
- }
- iResult = TRUE;
- }
- CloseStream();
- }
- else
- {
- SetIoError(IOERR_DOS, ::IoErr()); // Erreur pendant la lecture du fichier.
- }
- delete [] pSamples;
- }
-
- return iResult;
- }
- ///
-
- //----------------------------------------------------------------------------------------------------
- //======================================== Classe WAV_AudioC =========================================
- //----------------------------------------------------------------------------------------------------
- //
- // Fonctions spécialisées dans la gestion des fichiers WAVE
-
- /// Définitions
-
- #define fmt_ID MAKE_ID('f','m','t',' ')
- #define data_ID MAKE_ID('d','a','t','a')
-
- /* RIFF header */
- struct RIFFHeader
- {
- ULONG rh_RIFF; // RIFF
- ULONG rh_Size;
- ULONG rh_Format; // WAVE
- };
-
-
- /* RIFF chunk */
- struct RIFFChunk
- {
- ULONG rc_ID;
- ULONG rc_Size;
- };
-
-
- struct WaveFormat
- {
- WORD wf_Format; // WAVE_FORMAT_PCM
- WORD wf_Channels; // 1 = Mono, 2 = Stereo
- ULONG wf_SamplesPerSec; // Fréquence d'échantillonage.
- ULONG wf_AvgBytesPerSec; // Taux de transfert (nombre d'octets par seconde)
- WORD wf_BlockAlign; // Nombre d'octets à lire par sample.
- };
-
- /* wf_Format values */
- #define WAVE_FORMAT_PCM 1
-
- struct PCMData
- {
- UWORD pd_BitsPerSample; // Nombre de bits par échantillons.
- };
-
- ///
-
- /// WAV_AudioC::GetFileInfos()
- /****** Class WAV_AudioC/GetFileInfos ***************************************
- *
- * NAME
- * WAV_AudioC::GetFileInfos -- Analyse un fichier WAV.
- *
- * SYNOPSIS
- * result = WAV_AudioC::GetFileInfos()
- *
- * bool WAV_AudioC::GetFileInfos();
- *
- * FUNCTION
- * Analyse un fichier WAV afin d'obtenir la fréquence d'échantillonage, le
- * nombre d'échantillons du fichier et le nombre de canaux.
- * Si le fichier possède plus de 2 canaux, ou si les échantillons ne sont
- * pas codés sur 16 bits, le fichier est rejeté.
- * De plus, ce fichier doit être au format MicroSoft PCM à l'exclusion de
- * tout autre.
- *
- * RESULT
- * result - FALSE en cas d'erreur.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle
- *
- * SEE ALSO
- * MAUD_AudioC::GetFileInfos()
- * AIFF_AudioC::GetFileInfos()
- * CDDA_AudioC::GetFileInfos()
- * RAW_AudioC::GetFileInfos()
- *
- *****************************************************************************
- *
- */
-
-
- int WAV_AudioC::GetFileInfos()
- {
- struct WAV_fmt {struct WaveFormat sWaveFormat; // Format du bloc d'entête.
- struct PCMData sPCMData;
- };
-
- int iGotIt = FALSE;
- ULONG iChunkSize = 0;
- ULONG iRead;
- WAV_fmt sWavFmt;
-
- if (OpenStream() == IOERR_NONE)
- {
- // Rechercher le chunk 'fmt '.
-
- if ( (iChunkSize = LocateChunk('fmt ')) == sizeof(WAV_fmt) )
- {
- // Lire le bloc de format.
-
- if ( (iRead = Read(istr_bpFileHandle, &sWavFmt, iChunkSize)) == iChunkSize)
- {
- WORD wav_Format = _getword(sWavFmt.sWaveFormat.wf_Format);
- WORD wav_Channels = _getword(sWavFmt.sWaveFormat.wf_Channels);
- LONG wav_SamplFreq = _getlong(sWavFmt.sWaveFormat.wf_SamplesPerSec);
- WORD wav_BitsPerSmpl = _getword(sWavFmt.sPCMData.pd_BitsPerSample);
-
- // Contrôler les données de l'entête.
-
- if ( wav_Format == WAVE_FORMAT_PCM
- && wav_Channels > 0
- && wav_Channels < 3
- && wav_BitsPerSmpl == 16)
- {
- // Rechercher le nombre d'échantillons.
-
- istr_iChannelSize = LocateChunk('data') >> 1; // 16 bits par échantillon.
- if (wav_Channels == 2) istr_iChannelSize >>= 1; // Mode stéréo.
-
- if (istr_iChannelSize > 0)
- {
- SetNumFrames(istr_iChannelSize);
- iGotIt = istr_roFileInfo.OverrideSettings(wav_SamplFreq, wav_Channels);
- SetAudioFormat( (wav_Channels == 1) ? FORMAT_INTEL_MONO : FORMAT_INTEL_STEREO );
- if (!iGotIt) SetIoError(IOERR_INTERNAL, ERROR_OBJECT_WRONG_TYPE);
- }
- }
- }
- }
- CloseStream();
- }
-
- // Si le format du fichier n'est pas supporté (ou si le fichier ne peut être ouvert),
- // placer les codes d'erreur et modifier le code de type de fichier.
-
- if (!iGotIt)
- {
- SetFileType(AFT_BAD_WAV);
- SetIoError(IOERR_INTERNAL, ERROR_OBJECT_WRONG_TYPE);
- }
-
- return iGotIt;
- }
- ///
- /// WAV_AudioC::LocateChunk()
- /****** Class WAV_AudioC/LocateChunk ****************************************
- *
- * NAME
- * WAV_AudioC::LocateChunk -- Rechercher un chunk RIFF.
- *
- * SYNOPSIS
- * Size = WAV_AudioC::LocateChunk(ChunkID)
- *
- * ULONG WAV_AudioC::LocateChunk(ULONG);
- *
- * FUNCTION
- * Recherche un chunk RIFF dans le fichier. Le fichier doit avoir été ouvert
- * au préalable.
- *
- * INPUTS
- * ChunkID - Nom du chunk à trouver.
- *
- * RESULT
- * Size - Taille du chunk, ou 0 en cas d'erreur.
- *
- * NOTES
- * La fonction repositionne le pointeur de lecture juste après le chunk d'
- * entête (RIFFxxxxWAVE), puis saute tous les chunks rencontrés jusqu'à
- * trouver le chunk voulu ou la fin du fichier.
- *
- * BUGS
- * La fonction utilise la longueur de bloc mentionnée dans les chunks pour
- * repositionner le pointeur de lecture sur le chunk suivant. Il n'est pas
- * évident que cette longueur corresponde toujours à la taille réelle du
- * chunk, ce qui peut causer des problèmes de gestion (puisque dès lors, la
- * fonction sera incapable de retrouver le chunk demandé).
- *
- *****************************************************************************
- *
- */
-
-
- ULONG WAV_AudioC::LocateChunk(ULONG ChunkID)
- {
- RIFFChunk sChunk;
- ULONG iSize = 0;
- ULONG iRead;
-
- // Sauter le bloc d'entête (déjà connu puisque le fichier a été identifié
- // comme étant un fichier RIFF-WAVE).
-
- if (NewSeek(istr_bpFileHandle, sizeof(RIFFHeader), OFFSET_BEGINING) >= 0)
- {
- while ( (iRead = ::Read(istr_bpFileHandle, &sChunk, sizeof(RIFFChunk))) > 0)
- {
- iSize = _getlong(sChunk.rc_Size);
-
- if (sChunk.rc_ID == ChunkID) return iSize;
- if (NewSeek(istr_bpFileHandle, iSize, OFFSET_CURRENT) < 0) break;
- }
- }
-
- return (0L);
- }
- ///
- /// WAV_AudioC::SeekToAudio()
- /****** Class WAV_AudioC/SeekToAudio ****************************************
- *
- * NAME
- * WAV_AudioC::SeekToAudio -- Préparer la lecture du bloc audio.
- *
- * SYNOPSIS
- * Result = WAV_AudioC::SeekToAudio()
- *
- * bool WAV_AudioC::SeekToAudio();
- *
- * FUNCTION
- * Positionne le pointeur de lecture au début du bloc de données audio.
- * Le fichier WAV doit avoir été ouvert et initialisé avant d'appeler cette
- * fonction.
- *
- * RESULT
- * Result - FALSE en cas d'erreur.
- *
- * NOTES
- * Surdéfinition d'une fonction virtuelle.
- *
- * SEE ALSO
- * InputStreamC::SeekToAudio()
- * IFF_AudioC::SeekToAudio()
- *
- *****************************************************************************
- *
- */
-
- int WAV_AudioC::SeekToAudio()
- {
- return (LocateChunk('data') != 0);
- }
- ///
-
-