Solved

Translate from C to PAS (raw to wav)

Posted on 2000-02-15
12
912 Views
Last Modified: 2011-09-20
Hello,
I want to translate this code from C to Delphi (transform a raw sound file in a wav sound file, 16000 / 16 bits)

Thanks,

Jean-Pol
=====================

#include <stdio.h>
#include <sys/stat.h>
#include <windows.h>


long chunksize=0x10;
struct
{
                WORD    wFormatTag;
                WORD    wChannels;
                DWORD   dwSamplesPerSec;
                DWORD   dwAvgBytesPerSec;
                WORD    wBlockAlign;
                        WORD      wBitsPerSample;
} fmt;
int Raw2Wav(const char *rawfn, const char *wavfn, long frequency)
{
      struct _stat sb;
      if(!_stat(rawfn, &sb))            // OK
      {
            long samplecount=sb.st_size/2;
            long riffsize=samplecount*2+0x24;
            long datasize=samplecount*2;
            FILE *raw=fopen(rawfn,"rb");
            if(!raw) return -2;
            FILE *wav=fopen(wavfn,"wb");
            if(!wav)
            {
                  fclose(raw); return -3;
            }
            fwrite("RIFF",1,4,wav);
            fwrite(&riffsize,4,1,wav);
            fwrite("WAVEfmt ",1,8,wav);
            fwrite(&chunksize,4,1,wav);
            fmt.wFormatTag=1;      // PCM
            fmt.wChannels=1;      // MONO
            fmt.dwSamplesPerSec=frequency*1;
            fmt.dwAvgBytesPerSec=frequency*1*2;      // PCM 16 bits
            fmt.wBlockAlign=2;
            fmt.wBitsPerSample=16;
            fwrite(&fmt,sizeof(fmt),1,wav);
            fwrite("data",1,4,wav);
            fwrite(&datasize,4,1,wav);
            short buff[1024];
            while(!feof(raw))
            {
                  int cnt=fread(buff,2,1024,raw);
                  if(cnt==0) break;
                  fwrite(buff,2,cnt,wav);
            }
            fclose(raw);
            fclose(wav);
      }
      else      // File not found?
      {
            return -1;
      }
      return 0;
}
/*
int main(int argc, char arcv[])
{
      int ret=Raw2Wav("d:\\data\\ear\\pcm\\cmh1_st0058","c:\\temp\\essai.wav",16000);
}
*/

==========================
0
Comment
Question by:jpdupont
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
12 Comments
 

Expert Comment

by:brunohe
ID: 2522779
..and what's the problem?
0
 
LVL 1

Expert Comment

by:AttarSoftware
ID: 2522818
Similar to :

(This should help)

-----------------------------------

const
  chunkSize = $10 ;

type
  fmt = record
          wFormatTag       : word ;
          wChannels        : word ;
          dwSamplesPerSec  : longint ;
          dwAvgBytesPerSec : longint ;
          wBlockAlign      : word ;
          wBitsPerSample   : word ;
        end ;

function Raw2Wav( rawFn : string ; waveFn : string ; frequency : longint ) : longint ;
var
  sb : t_stat ; // WHAT IS THIS?
  sampleCount : longint ;
  riffSize : longint ;
  dataSize : longint ;
  raw : file ;
  wav : file ;
  buff : array [ 0 .. 1024 ] of short ;
  cnt : longint ;
begin
  if( not _stat( rawfn, &sb ) ) then // OK
  begin
    samplecount := sb.st_size / 2 ;
    riffsize := samplecount * 2 + $24 ;
    datasize := samplecount * 2 ;
    AssignFile( raw, rawfn ) ;
    {$i-}Reset( raw, 1 ) ;{$i+}
    if( ioResult <> 0 ) then
    begin
      result := -2 ;
      exit ;
    end ;
    AssignFile( wav, wavfn ) ;
    {$i-}Rewrite( wav, 1 ) ;{$i+}
    if( ioResult <> 0 ) then
    begin
      CloseFile( raw ) ;
      result := -3 ;
      exit ;
    end ;
    BlockWrite( wav, "RIFF", 4 ) ;
    BlockWrite( wav, riffSize, 4 ) ;
    BlockWrite( wav, "WAVEfmt", 8 ) ;
    BlockWrite( wav, chunkSize, 4 ) ;

    fmt.wFormatTag := 1 ; // PCM
    fmt.wChannels := 1 ; // MONO
    fmt.dwSamplesPerSec := frequency * 1 ;
    fmt.dwAvgBytesPerSec := frequency * 1 * 2 ; // PCM 16 bits
    fmt.wBlockAlign := 2 ;
    fmt.wBitsPerSample := 16 ;
    BlockWrite( wav, fmt, sizeof(fmt) ) ;
    BlockWrite( wav, 'data', 4 ) ;
    BlockWrite( wav, dataSize, 4 ) ;
    while( not EOF( raw ) )
    begin
      BlockRead( raw, buff, 1024 * sizeof( short ), cnt ) ;
      if( cnt = 0 ) then break ;
      BlockWrite( wav, buf, cnt * sizeof( short ) ) ;
    end ;
    CloseFile( raw ) ;
    CloseFile( wav ) ;
  end else // File not found?
  begin
    result := -1;
    exit ;
  end ;
  return 0;
end ;

Hope it does,

Good luck

Tim.
0
 
LVL 1

Expert Comment

by:AttarSoftware
ID: 2522827
PS:  I havent compiled it, so you might get a few errors, and BlockRead and BlockWrite may have their parameters the wrong way round, but as it is from memory, I can accept that...  Hope you can too ;O)

Tim.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:jpdupont
ID: 2522829
The problem is :

I'm not able to translate this C code to a .PAS code ? (I dont "speak" C or C++)

Could you do this for me ?

Thanks,

JP
0
 
LVL 6

Expert Comment

by:Jaymol
ID: 2522896
Tim (AttarSoftware) just did it for you!

John.
0
 

Author Comment

by:jpdupont
ID: 2522944
sb : t_stat ; // WHAT IS THIS?

Error when compiling here and after ...
0
 
LVL 1

Expert Comment

by:AttarSoftware
ID: 2523072
Ok, change the top 23 lines to:

function Raw2Wav( rawFn : string ; waveFn : string ; frequency : longint ) : longint ;
var
  sz : longint ; //CHANGED!
  sampleCount : longint ;
  riffSize : longint ;
  dataSize : longint ;
  raw : file ;
  wav : file ;
  buff : array [ 0 .. 1024 ] of short ;
  cnt : longint ;
begin
  AssignFile( raw, rawfn ) ;
  {$i-}Reset( raw, 1 ) ;{$i+}
  if( ioResult <> 0 ) then
  begin
    result := -2 ;
    exit ;
  end ;
  samplecount := FileSize( raw ) div 2 ;
  riffsize := samplecount * 2 + $24 ;
  datasize := samplecount * 2 ;

and get rid of:

  end else // File not found?
  begin
    result := -1;
    exit ;
  end ;

at the bottom...

Better?

Hope so ;O)

Tim.
0
 
LVL 1

Expert Comment

by:AttarSoftware
ID: 2523081
Heh, actually get rid of the

  sz : longint // CHANGED

line too :O)

  Almost hometime and Delphi from memory = confusion and too many defined variables ;O)

Good luck,

Tim.
0
 

Author Comment

by:jpdupont
ID: 2523792
Here the code (corrected ?). Compiles OK but the Wav file is not a correct wav file. (It seems to be 2x the size of the raw file). If you want give me a email address to send a test raw file.

JP

=============
type
  fmt = record
    wFormatTag: word;
    wChannels: word;
    dwSamplesPerSec: longint;
    dwAvgBytesPerSec: longint;
    wBlockAlign: word;
    wBitsPerSample: word;
  end;


function BabRaw2Wav(rawFn: string; waveFn: string; frequency: longint): longint;
var
  sampleCount: longint;
  riffSize: longint;
  dataSize: longint;
  chunkSize : longint;
  raw: file;
  wav: file;
  buff: array[0..1024] of short;
  cnt: longint;
  Afmt:fmt;
begin
  chunkSize := $10;
  AssignFile(raw, rawfn);
  AssignFile(wav, wavefn);
{$I-}Reset(raw, 1); {$I+}
  if (ioResult <> 0) then
  begin
    result := -2;
    exit;
  end;
  samplecount := FileSize(raw) div 2;
  riffsize := samplecount * 2 + $24;
  datasize := samplecount * 2;
{$I-}Rewrite(wav, 1); {$I+}
  if (ioResult <> 0) then
  begin
    CloseFile(raw);
    result := -3;
    exit;
  end;
  BlockWrite(wav, 'RIFF', 4);
  BlockWrite(wav, riffSize, 4);
  BlockWrite(wav, 'WAVEfmt', 8);
  BlockWrite(wav, chunkSize, 4);
  Afmt.wFormatTag := 1; // PCM
  Afmt.wChannels := 1; // MONO
  Afmt.dwSamplesPerSec := frequency * 1;
  Afmt.dwAvgBytesPerSec := frequency * 1 * 2; // PCM 16 bits
  Afmt.wBlockAlign := 2;
  Afmt.wBitsPerSample := 16;
  BlockWrite(wav, Afmt, sizeof(fmt));
  BlockWrite(wav, 'data', 4);
  BlockWrite(wav, dataSize, 4);
  while (not EOF(raw)) do
  begin
    BlockRead(raw, buff, 1024 * sizeof(short), cnt);
    if (cnt = 0) then break;
    BlockWrite(wav, buff, cnt * sizeof(short));
  end;
  CloseFile(raw);
  CloseFile(wav);
end;
0
 
LVL 1

Accepted Solution

by:
AttarSoftware earned 200 total points
ID: 2526219
Unfortunatly, I cannot recieve attatchments at work :O(

(Draconian virus-paranoid email policy)

  It is probably to do with the size of the data that it writes during the while loop...  How big are short integers in C?  I guess that Delphi ones are a different size...  try changing the array to an array of word (and the blockwrite to cnt * sizeof(word) and see if that helps...)  If not word, try byte (and cnt * sizeof(byte))

Good luck

Tim.
0
 

Author Comment

by:jpdupont
ID: 2526317
Hello,

All seems to be good now :

1/ BlockWrite(wav, 'WAVEfmt', 8);
must be BlockWrite(wav, 'WAVEfmt ', 8);
(with a space after 'fmt')

2/ Byte is the good value.

Thanks, Tim !

BTW,
I found good wav info on

http://webperso.alma-net.net/burel/sp/tech_000/tech0.htm 
(in french)
and

http://technology.niagarac.on.ca/courses/comp630/WavFileFormat.html

JP
0
 

Author Comment

by:jpdupont
ID: 2526323
Thanks !
0

Featured Post

[Webinar] Code, Load, and Grow

Managing multiple websites, servers, applications, and security on a daily basis? Join us for a webinar on May 25th to learn how to simplify administration and management of virtual hosts for IT admins, create a secure environment, and deploy code more effectively and frequently.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question