; Save a loaded sample as standard iff/8svx sample
; Curt Esser  <camge@ix.netcom.com>
; pd - use in any way you like
; but please send me a copy of any improvements
; last modified  Dec 04 1998

;=== Here is an explanation of the format, which I found on the Net ====

;The first 12 bytes of an IFF file are used to distinguish between an Amiga
;picture (FORM-ILBM), an Amiga sound sample (FORM-8SVX), or other file
;conforming to the IFF specification.  The middle 4 bytes is the count of
;bytes that follow the "FORM" and byte count longwords.  (Numbers are stored
;in M68000 form, high order byte first.)

;FutureSound audio file, 15000 samples at 10.000KHz, file is 15048 bytes long.

;0000: 464F524D 00003AC0 38535658 56484452    FORM..:.8SVXVHDR
;      F O R M     15040 8 S V X  V H D R

;0010: 00000014 00003A98 00000000 00000000    ......:.........
;            20    15000        0        0

;0020: 27100100 00010000 424F4459 00003A98    '.......BODY..:.
;     10000 1 0    1.0   B O D Y     15000

;0000000..03 = "FORM", identifies this as an IFF format file.
;FORM+00..03 (ULONG) = number of bytes that follow.  (Unsigned long int.)
;FORM+03..07 = "8SVX", identifies this as an 8-bit sampled voice.

;????+00..03 = "VHDR", Voice8Header, describes the parameters for the BODY.
;VHDR+00..03 (ULONG) = number of bytes to follow.
;VHDR+04..07 (ULONG) = samples in the high octave 1-shot part.
;VHDR+08..0B (ULONG) = samples in the high octave repeat part.
;VHDR+0C..0F (ULONG) = samples per cycle in high octave (if repeating), else 0.

;PLEASE NOTE:   in spite of what this says ^^^
;I examined many 8svx samples to see what to put here.  I found that always
;this value was either 0 or 32.  It didn't seem to have anything to do with
;whether the sample had a loop or not.  In general, music samples (the kind
;you would use in a tracker) had 32, other samples (sound effects, speech)
;had a 0.  But I also found exceptions (music samples with 0, etc.)
;I also didn't find any programs that seemed to use this value for anything.
;I have simply made the routine to use 32 for all samples.
;If anyone knows different, please let me know.


;VHDR+10..11 (UWORD) = samples per second.  (Unsigned 16-bit quantity.)
;VHDR+12     (UBYTE) = number of octaves of waveforms in sample.
;VHDR+13     (UBYTE) = data compression (0=none, 1=Fibonacci-delta encoding).
;VHDR+14..17 (FIXED) = volume.  (The number 65536 means 1.0 or full volume.)

;????+00..03 = "BODY", identifies the start of the audio data.
;BODY+00..03 (ULONG) = number of bytes to follow.
;BODY+04..NNNNN      = Data, signed bytes, from -128 to +127.

;===============================================================

; Call with the sample # to save, and the full save path $tring

; returns -1 (True) sucess
;          0 (False) sample doesn't exist
;          1 disk error - save unsuccesful  :(

Function.b SaveSample{samplenumber.w,saveIFF$}

If Peek.l(Addr Sound(samplenumber))                          ;make sure sample exists

;   Now we read the necessary information into our variables

  sndstart.l=Peek.l(Addr Sound(samplenumber))                ;start of sample data
  slen.l=(Peek.w(Addr Sound (samplenumber)+6) AND $FFFF)*2   ;bytes of sample data

; -- the total disk file length less 8 bytes for "FORM" + length:

  tlen.l=slen+40

; -- the looping information:

  loop.l=Peek.l(Addr Sound (samplenumber)+8)                 ;start of looping part
  lpln.l=(Peek.w(Addr Sound (samplenumber)+12) AND $FFFF)*2  ;length of loop
  ones.l=loop-sndstart                                       ;length of 1 shot part
  cycl.l=32                                                  ;seems to be standard?

; -- the frequency:

  per.l=(Peek.w(Addr Sound(samplenumber)+4) AND $FFFF)       ;the sample period
  persec.w= 3579440/per                                      ;the actual frequency

  If WriteFile (0,saveIFF$)
    error=-1
    FileOutput 0
    Print "FORM"             ;start of IFF header
    WriteMem 0,&tlen,4       ;total bytes following the header
    Print "8SVXVHDR"         ;8svx sample ID, and start of Voice Header
    temp.l=20
    WriteMem 0,&temp,4       ;bytes in Voice Header chunk
    WriteMem 0,&ones,4       ;data bytes in 1 shot part
    temp.l=0
    WriteMem 0,&lpln,4       ;for looping (length of loop)
    WriteMem 0,&cycl,4       ;"     "     "
    WriteMem 0,&persec,2     ;frequency of the sample
    tempb.b=1
    WriteMem 0,&tempb,1      ;octaves
    WriteMem 0,&temp,1       ;compression (0=not compressed)
    temp.l=65536             ;volume (full volume)
    WriteMem 0,&temp,4
    Print "BODY"             ;start of Body chunk
    WriteMem 0,&slen,4       ;bytes of actual sample data
    WriteMem 0,sndstart,slen ;OK, finally!  Write the data
    CloseFile 0
    Use Window 0
  Else
    error=2
  EndIf

Else
  error=0                    ;sorry, that sample doesn't exist!
EndIf

Function Return error

End Function
