Writing an audio file?

Just starting out? Need help? Post your questions and find answers here.
bloiiing
User
User
Posts: 14
Joined: Sun Jan 10, 2010 7:32 pm

Writing an audio file?

Post by bloiiing »

Hello!

I would like to know if there is a way to encode and write an audio file? Is there a framework for PB? I want to write mp3 or ogg files...

Thank you and have a nice day.
infratec
Always Here
Always Here
Posts: 6883
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Writing an audio file?

Post by infratec »

A WAV file is no problem (search for RIFF here in the forum)
MP3 needs an external lib
Ogg should be possible if you import the needed functions with Import from
vorbisfile.lib and ogg.lib
bloiiing
User
User
Posts: 14
Joined: Sun Jan 10, 2010 7:32 pm

Re: Writing an audio file?

Post by bloiiing »

infratec wrote:A WAV file is no problem (search for RIFF here in the forum)
MP3 needs an external lib
Ogg should be possible if you import the needed functions with Import from
vorbisfile.lib and ogg.lib
Thank you infratec. It helps for a wav file. Do you know the name of an mp3 lib? And where are the vorbisfile.lib and ogg.lib? And where is the doc for them? Do they come with PB software?

Thank you.
infratec
Always Here
Always Here
Posts: 6883
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Writing an audio file?

Post by infratec »

Name of a mp3 lib ??? LAME :!:

ogg and vorbis are delivered with PB. You can simply use

Code: Select all

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

;
; https://xiph.org/vorbis/doc/libvorbis/overview.html
; https://github.com/xiph/vorbis/blob/master/include/vorbis/codec.h
;

#OV_FALSE      = -1
#OV_EOF        = -2
#OV_HOLE       = -3

#OV_EREAD      = -128
#OV_EFAULT     = -129
#OV_EIMPL      = -130
#OV_EINVAL     = -131
#OV_ENOTVORBIS = -132
#OV_EBADHEADER = -133
#OV_EVERSION   = -134
#OV_ENOTAUDIO  = -135
#OV_EBADPACKET = -136
#OV_EBADLINK   = -137
#OV_ENOSEEK    = -138

#OV_ECTL_RATEMANAGE_GET       = $10
#OV_ECTL_RATEMANAGE_SET       = $11
#OV_ECTL_RATEMANAGE_AVG       = $12
#OV_ECTL_RATEMANAGE_HARD      = $13
#OV_ECTL_RATEMANAGE2_GET      = $14
#OV_ECTL_RATEMANAGE2_SET      = $15

#OV_ECTL_LOWPASS_GET          = $20
#OV_ECTL_LOWPASS_SET          = $21

#OV_ECTL_IBLOCK_GET           = $30
#OV_ECTL_IBLOCK_SET           = $31

#OV_ECTL_COUPLING_GET         = $40
#OV_ECTL_COUPLING_SET         = $41


Structure ogg_stream_state Align #PB_Structure_AlignC
  *body_data
  body_storage.l
  body_fill.l
  body_returned.l
  
  *lacing_vals
  *granule_vals
  
  lacing_storage.l
  lacing_fill.l
  lacing_packet.l
  lacing_returned.l
  
  header.a[282]
  header_fill.i
  
  e_o_s.i
  b_o_s.i
  serialno.l
  pageno.l
  
  packetno.q
  granulepos.q
EndStructure


Structure ogg_page Align #PB_Structure_AlignC
  *header
  header_len.l
  *body
  body_len.l
EndStructure


Structure ogg_packet Align #PB_Structure_AlignC
  *packet
  bytes.l
  b_o_s.l
  e_o_s.l
  
  granulepos.q
  packetno.q
EndStructure


Structure oggpack_buffer Align #PB_Structure_AlignC
  endbyte.l
  endbit.i
  
  *buffer
  *ptr
  storage.l
EndStructure


Structure vorbis_info Align #PB_Structure_AlignC
  version.i
  channels.i
  rate.l
  
  bitrate_upper.l
  bitrate_nominal.l
  bitrate_lower.l
  bitrate_window.l
  
  *codec_setup
EndStructure


Structure vorbis_comment Align #PB_Structure_AlignC
  *user_comments
  *comment_lengths
  comments.i
  *vendor
EndStructure


Structure vorbis_block Align #PB_Structure_AlignC
  *pcm
  opb.oggpack_buffer
  
  lW.l
  W.l
  nW.l
  pcmend.i
  mode.i
  
  eofflag.i
  granulepos.q
  sequence.q
  *vd.vorbis_dsp_state
  
  *localstore
  localtop.l
  localalloc.l
  totaluse.l
  *reap.alloc_chain
  
  glue_bits.l
  time_bits.l
  floor_bits.l
  res_bits.l
  
  *internal
EndStructure


Structure vorbis_dsp_state Align #PB_Structure_AlignC
  analysisp.i
  *vi.vorbis_info
  
  *pcm
  *pcmret
  pcm_storage.i
  pcm_current.i
  pcm_returned.i
  
  preextrapolate.i
  eofflag.i
  
  lW.l
  W.l
  nW.l
  centerW.l
  
  granulepos.q
  sequence.q
  
  glue_bits.q
  time_bits.q
  floor_bits.q
  res_bits.q
  
  *backend_state
EndStructure



ImportC "ogg.lib"
  
  ; Encoding related
  ogg_stream_packetin.i(*os.ogg_stream_state, *op.ogg_packet)
  ogg_stream_pageout(*os.ogg_stream_state, *og.ogg_page)
  ogg_stream_flush.i(*os.ogg_stream_state, *og.ogg_page)
  
  ; General
  ogg_stream_clear(*os.ogg_stream_state)
  ogg_stream_init.i(*os.ogg_stream_state, serialno.i)
  ogg_page_eos.i(*og.ogg_page)
  
EndImport

ImportC "vorbisfile.lib"
  
  ; Functions used by both decode And encode
  vorbis_block_clear(*vb.vorbis_block)
  vorbis_block_init(*v.vorbis_dsp_state, *vb.vorbis_block)
  vorbis_dsp_clear(*v.vorbis_dsp_state)
  vorbis_granule_time.d(*v.vorbis_dsp_state, granulepos.l)
  vorbis_info_blocksize(*vi.vorbis_info, zo.i)
  vorbis_info_clear(*vi.vorbis_info)
  vorbis_info_init(*vi.vorbis_info)
  vorbis_version_string.i()
  
  ; Decoding
  vorbis_packet_blocksize.l(*vi.vorbis_info, *op.ogg_packet)
  vorbis_synthesis.i(*vb.vorbis_block , *op.ogg_packet)
  vorbis_synthesis_blockin.i(*v.vorbis_dsp_state , *vb.vorbis_block)
  vorbis_synthesis_halfrate.i(*v.vorbis_info, flag.i)
  vorbis_synthesis_headerin.i(*vi.vorbis_info, *vc.vorbis_comment, *op.ogg_packet)
  vorbis_synthesis_idheader.i(*op.ogg_packet)
  vorbis_synthesis_init.i(*v.vorbis_dsp_state, *vi.vorbis_info)
  vorbis_synthesis_lapout.i(*v.vorbis_dsp_state, *pcm)
  vorbis_synthesis_pcmout.i(*v.vorbis_dsp_state, *pcm)
  vorbis_synthesis_read.i(*v.vorbis_dsp_state, samples.i)
  vorbis_synthesis_restart.i(*v.vorbis_dsp_state)
  vorbis_synthesis_trackonly.i(*vb.vorbis_block , *op.ogg_packet)
  
  
  ; Encoding
  vorbis_analysis(*vb.vorbis_block, *op.ogg_packet)
  vorbis_analysis_blockout.i(*v.vorbis_dsp_state, *vb.vorbis_block)
  vorbis_analysis_buffer.i(*v.vorbis_dsp_state, vals.i)
  vorbis_analysis_headerout.i(*v.vorbis_dsp_state, *vc.vorbis_comment, *op.ogg_packet, *op_comm.ogg_packet, *op_code.ogg_packet)
  vorbis_analysis_init.i(*v.vorbis_dsp_state, *vi.vorbis_info)
  vorbis_analysis_wrote(*v.vorbis_dsp_state, vals.i)
  vorbis_bitrate_addblock(*vbvorbis_block)
  vorbis_bitrate_flushpacket(*vd.vorbis_dsp_state, *op.ogg_packet)
  
  
  vorbis_encode_ctl.i(*vi.vorbis_info, request.i, *arg)
  vorbis_encode_init.i(*vi.vorbis_info, channels.l, rate.l, max_bitrate.l, nominal_bitrate.l, min_bitrate.l)
  vorbis_encode_init_vbr.i(*vi.vorbis_info, channels.l, rate.l, base_quality.f)
  vorbis_encode_setup_init.i(*vi.vorbis_info)
  vorbis_encode_setup_managed.i(*vi.vorbis_info, channels.l, rate.l, max_bitrate.l, nominal_bitrate.l, min_bitrate.l)
  vorbis_encode_setup_vbr.i(*vi.vorbis_info, channels.l, rate.l, base_quality.f)
  
  ; Metadata
  vorbis_comment_add(*vc.vorbis_comment, comment.p-ascii)
  vorbis_comment_add_tag(*vc.vorbis_comment, tag.p-ascii, contents.p-ascii)
  vorbis_comment_clear(*vc.vorbis_comment)
  vorbis_comment_init(*vc.vorbis_comment)
  vorbis_comment_query.i(*vc.vorbis_comment, tag.p-ascii, count.i)
  vorbis_comment_query_count.i(*vc.vorbis_comment, tag.p-ascii)
  vorbis_commentheader_out.i(*vc.vorbis_comment, *op.ogg_packet)
  
EndImport


Procedure.s Vorbis_GetErrorText(Error.i)
  
  Protected Result$
  
  
  Select Error
    Case #OV_FALSE : Result$ = "OV_FALSE"
    Case #OV_EOF : Result$ = "OV_EOF"
    Case #OV_HOLE : Result$ = "OV_HOLE"
    Case #OV_EREAD : Result$ = "OV_EREAD: A read from media returned an error."
    Case #OV_EFAULT : Result$ = "OV_EFAULT: Internal logic fault; indicates a bug or heap/stack corruption."
    Case #OV_EIMPL : Result$ = "OV_EIMPL: The bitstream makes use of a feature not implemented in this library version."
    Case #OV_EINVAL : Result$ = "OV_EINVAL: Invalid argument value."
    Case #OV_ENOTVORBIS : Result$ = "OV_ENOTVORBIS: Bitstream/page/packet is not Vorbis data."
    Case #OV_EBADHEADER : Result$ = "OV_EBADHEADER: Invalid Vorbis bitstream header."
    Case #OV_EVERSION : Result$ = "OV_EVERSION: Vorbis version mismatch."
    Case #OV_ENOTAUDIO : Result$ = "OV_ENOTAUDIO: Packet data submitted to vorbis_synthesis is not audio data."
    Case #OV_EBADPACKET : Result$ = "OV_EBADPACKET: Invalid packet submitted to vorbis_synthesis."
    Case #OV_EBADLINK : Result$ = "OV_EBADLINK: Invalid stream section supplied to libvorbis/libvorbisfile, or the requested link is corrupt."
    Case #OV_ENOSEEK : Result$ = "OV_ENOSEEK: Bitstream is not seekable."
    Default : Result$ = "OV unknown error: " + Str(Error)
  EndSelect
  
  ProcedureReturn Result$
  
EndProcedure




CompilerIf #PB_Compiler_IsMainFile
  
  ; https://github.com/xiph/vorbis/blob/master/examples/encoder_example.c
  
  ; WAV file wich works (44100 Hz PCM 16bit Stereo)
  ; http://www.music.helsinki.fi/tmt/opetus/uusmedia/esim/a2002011001-e02.wav
  
  #Read = 1024
  
  Define *readbuffer
  
  Define os.ogg_stream_state
  Define og.ogg_page
  Define op.ogg_packet
  Define vi.vorbis_info
  Define vc.vorbis_comment
  Define vd.vorbis_dsp_state
  Define vb.vorbis_block
  
  Define header.ogg_packet
  Define header_comm.ogg_packet
  Define header_code.ogg_packet
  
  Define.i eos, ret
  Define.i i, founddata
  
  Define result.i, bytes.i, *floatbuffer
  
  Define Filename$, InFile.i, OutFile.i, *fptr, WVal.u
  
  
  Filename$ = OpenFileRequester("Choose a 44.1k WAV file", "", "WAV|*.wav", 0)
  If Filename$
    InFile = ReadFile(#PB_Any, Filename$)
    If InFile
      
      *readbuffer = AllocateMemory(#Read * 4 + 44)
      If *readbuffer
        
        While i < 30 And Not Eof(InFile)
          If ReadData(InFile, *readbuffer, 2) = 2
            If PeekS(*readbuffer, 2, #PB_Ascii) = "da"
              founddata = #True
              ReadData(InFile, *readbuffer, 6)
              Break
            EndIf
          EndIf
          i + 1
        Wend
        
        
        vorbis_info_init(@vi)
        
;         ret = vorbis_encode_init_vbr(@vi, 2, 44100, 0.4)
;         
;         ret = vorbis_encode_setup_managed(@vi, 2, 44100, -1, 128000, -1)
;         ret = vorbis_encode_ctl(@vi, #OV_ECTL_RATEMANAGE2_SET, #Null)
;         ret = vorbis_encode_setup_init(@vi)
        
        ret = vorbis_encode_init_vbr(@vi, 2, 44100, 0.1)
        
        If Not ret
          
          vorbis_comment_init(@vc)
          vorbis_comment_add_tag(@vc, "ENCODER", "OggVorbis.pbi")
          
          vorbis_analysis_init(@vd, @vi)
          vorbis_block_init(@vd, @vb)
          
          RandomSeed(Date())
          ogg_stream_init(@os, Random(100000000))
          
          vorbis_analysis_headerout(@vd, @vc, @header, @header_comm, @header_code)
          ogg_stream_packetin(@os, @header)
          
          ogg_stream_packetin(@os, @header_comm)
          ogg_stream_packetin(@os, @header_code)
          
          OutFile = CreateFile(#PB_Any, GetPathPart(Filename$) + GetFilePart(Filename$, #PB_FileSystem_NoExtension) + ".ogg")
          If OutFile
            
            While Not eos
              result = ogg_stream_flush(@os, @og)
              If result = 0
                Break
              EndIf
              WriteData(OutFile, og\header, og\header_len)
              WriteData(OutFile, og\body, og\body_len)
            Wend
            
            
            While Not eos
              bytes = ReadData(InFile, *readbuffer, #Read * 4)
              If bytes = 0
                vorbis_analysis_wrote(@vd, 0)
              Else
                *floatbuffer = vorbis_analysis_buffer(@vd, #Read)
                
                For i = 0 To bytes/4 - 1
                  
                  *fptr = PeekI(*floatbuffer)
                  WVal = (PeekA(*readbuffer + i * 4 + 1) << 8) | PeekA(*readbuffer + i * 4)
                  PokeF(*fptr + i * SizeOf(float), WVal / 32768)
                  
                  *fptr = PeekI(*floatbuffer + SizeOf(Integer))
                  WVal = (PeekA(*readbuffer + i * 4 + 3) << 8) | PeekA(*readbuffer + i * 4 + 2)
                  PokeF(*fptr + i * SizeOf(float), WVal / 32768)
                  
                Next i
                
                vorbis_analysis_wrote(@vd, i)
                
              EndIf
              
              While vorbis_analysis_blockout(@vd, @vb) = 1
                vorbis_analysis(@vb, #Null)
                vorbis_bitrate_addblock(@vb)
                
                While vorbis_bitrate_flushpacket(@vd, @op)
                  ogg_stream_packetin(@os, @op)
                  
                  While Not eos
                    result = ogg_stream_pageout(@os, @og)
                    If result = 0
                      Break
                    EndIf
                    
                    WriteData(OutFile, og\header, og\header_len)
                    WriteData(OutFile, og\body, og\body_len)
                    
                    If ogg_page_eos(@og)
                      eos = #True
                    EndIf
                  Wend
                  
                Wend
              Wend
              
            Wend
            
            ogg_stream_clear(@os)
            vorbis_block_clear(@vb)
            vorbis_dsp_clear(@vd)
            vorbis_comment_clear(@vc)
            vorbis_info_clear(@vi)
            
            CloseFile(OutFile)
          EndIf
        EndIf
        
        FreeMemory(*readbuffer)
      EndIf
      
      CloseFile(InFile)
    EndIf
  EndIf
  
CompilerEndIf
Last edited by infratec on Thu Mar 26, 2020 12:17 pm, edited 1 time in total.
bloiiing
User
User
Posts: 14
Joined: Sun Jan 10, 2010 7:32 pm

Re: Writing an audio file?

Post by bloiiing »

Thank you very very much. I'm going to take a look of this.

Have a great day.
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Writing an audio file?

Post by IdeasVacuum »

Others have worked on similar stuff in the past, no doubt it would help to see their code:

Generate sfxr Sound Effects, in-game

QBPlay_1.5.zip (Links to the RS BASIC Backups List)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User_Russian
Addict
Addict
Posts: 1443
Joined: Wed Nov 12, 2008 5:01 pm
Location: Russia

Re: Writing an audio file?

Post by User_Russian »

infratec wrote:MP3 needs an external lib
Possible use acm functions. https://docs.microsoft.com/en-us/window ... -functions
infratec
Always Here
Always Here
Posts: 6883
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Writing an audio file?

Post by infratec »

I extended and corrected my stuff above.

It includes now the example from the vorbis site.

In general it works, but ....
I don't know why the sound is messy in the ogg file.
bloiiing
User
User
Posts: 14
Joined: Sun Jan 10, 2010 7:32 pm

Re: Writing an audio file?

Post by bloiiing »

Ok. I have a work now. I am going to take a look at this code.

Thank you. Have a nice day!
Post Reply