Search code examples
delphiwinapidelphi-7wav

Failed to read list chunk using mmio function?


This is part of my code for reading a .wav file

    //Variable
    wavehdr:TWaveHeader;
    ckiRIFF,ckiFmt,ckiData,ckiLIST: TMMCKInfo;
    mmioinfo: PMMIOInfo;
    waveFmt: TWaveFormatEx;
    buf: Array of smallint;
    buf_recon: Array of double;
    list:Array of longint; // THIS IS MY GUESS so it's definetly not work
    HMMIO: hFile;

    //Locate the "RIFF" chunk
    ckiRIFF.fccType := mmioStringToFOURCC('WAVE',0);
    mmioDescend(HMMIO, @ckiRIFF, nil, MMIO_FINDRIFF);
    mmioAscend(HMMIO, @ckiRIFF, MMIO_FINDRIFF);

    //Locate the "FMT" subchunk
    ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);
    mmioDescend(HMMIO, @ckiFmt, nil, MMIO_FINDCHUNK);
    mmioRead(HMMIO, @waveFmt, ckiFmt.cksize);
    mmioAscend(HMMIO, @ckiFmt, 0);

    //Locate the "LIST" chunk (THIS PART IS NOT WORK)
    ckiLIST.fccType := mmioStringToFOURCC('LIST',0);
    mmioDescend(HMMIO, @ckiLIST, nil, MMIO_FINDLIST);
    mmioRead(HMMIO, @list, ckiLIST.cksize);
    mmioAscend(HMMIO, @ckiFmt, 0);

    //Locate the "data" subchunk
    ckiData.ckid := mmioStringToFOURCC('data', 0);
    if (mmioDescend(HMMIO, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then begin
    SetLength(buf, ckiData.cksize);
    mmioRead(HMMIO, PAnsiChar(buf), ckiData.cksize);

And it work just perfect until i realized that i missed the LIST chunk, where i only manage to get 'LIST'. Here an example for file before i read and write it back and there is list chunk and it's data enter image description here

and here is after i read and write it back enter image description here

the part i marked gone. So if anyone know what my mistake here please help me

EDIT 1

enter image description here


Solution

  • There are many problems with your code:

    1. You are not checking for errors.
    2. You are not allocating any memory for the list before reading it.
    3. You are not reading the "LIST" chunk correctly anyway, because there is no "LIST" chunk in WAV files to begin with. What you are trying to read is an "INFO" chunk that is a LIST type. So you have to find and descend into the "INFO" chunk, descend into and read its sub-chunks as needed, and then ascend back into the RIFF chunk.
    4. You are ascending out of the "RIFF" chunk when you should not be.

    Try this instead:

    var
      wavehdr: TWaveHeader;
      ckiRIFF, ckiFmt, ckiData, ckiLIST, ckiINAM: TMMCKInfo;
      mmioinfo: PMMIOInfo;
      waveFmt: TWaveFormatEx;
      buf: Array of smallint;
      buf_recon: Array of double;
      HMMIO: hFile;
    begin
      ...
      //Locate the "RIFF" chunk
      ckiRIFF.fccType := mmioStringToFOURCC('WAVE',0);
      if mmioDescend(HMMIO, @ckiRIFF, nil, MMIO_FINDRIFF) = 0 then
      begin
        //Locate the "FMT" subchunk
        ZeroMemory(@waveFmt, SizeOf(waveFmt));
        ckiFmt.ckid := mmioStringToFOURCC('fmt', 0);
        if mmioDescend(HMMIO, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = 0 then
        begin
          // technically, you should use a dynamic-length buffer instead of a static buffer
          mmioRead(HMMIO, @waveFmt, ckiFmt.cksize);
          mmioAscend(HMMIO, @ckiFmt, 0);
        end;
    
        //Locate the "INFO" chunk
        ckiLIST.fccType := mmioStringToFOURCC('INFO', 0);
        if mmioDescend(HMMIO, @ckiLIST, @ckiRIFF, MMIO_FINDLIST) = 0 then
        begin
          //Locate the "INAM" chunk
          ckiINAM.fccType := mmioStringToFOURCC('INAM', 0);
          if mmioDescend(HMMIO, @ckiINAM, @ckiLIST, MMIO_FINDCHUNK) = 0 then
          begin
            // read chunk data as needed...
            mmioAscend(HMMIO, @ckiINAM, 0);
          end;
          mmioAscend(HMMIO, @ckiLIST, 0);
        end;
    
        //Locate the "data" subchunk
        ckiData.ckid := mmioStringToFOURCC('data', 0);
        if (mmioDescend(HMMIO, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then
        begin
          SetLength(buf, ckiData.cksize);
          mmioRead(HMMIO, PAnsiChar(buf), ckiData.cksize);
          mmioAscend(HMMIO, @ckiData, 0);
        end;
        ...
      end;
      ...
    end;