Advertisement
Guest User

Untitled

a guest
Dec 13th, 2012
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.45 KB | None | 0 0
  1.  
  2. // code to convert ogg files to little inferno sound resources
  3. // dec 13, 2012 - allan blomquist
  4.  
  5. #define _CRT_SECURE_NO_WARNINGS
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. #include <ogg/ogg.h>
  10. #include <vorbis/codec.h>
  11.  
  12. #include <vector>
  13.  
  14. struct SoundHeader
  15. {
  16.     int totalSampleCountPerChannel;
  17.     int oggTotalDataSizeBytes;
  18.     int vorbisMarkersSizeBytes;
  19.     int vorbisWorkingSetSizeBytes;
  20.     int vorbisPacketsSizeBytes;
  21.     int samplesPerSec;
  22.     int channels;
  23. };
  24.  
  25. struct StreamMarker
  26. {
  27.     int packetStreamByteOffset;
  28.     int pcmSampleOffset;
  29.     int packetIdx;
  30. };
  31.  
  32. struct VorbisPacket
  33. {
  34.     int sizeBytes;
  35.     unsigned char *pData;
  36. };
  37.  
  38. int main( int argc, const char *argv[] )
  39. {
  40.     FILE *fSrc = fopen( argv[1], "rb" );
  41.  
  42.     // get size of ogg src file
  43.     fseek( fSrc, 0, SEEK_END );
  44.     int oggSizeBytes = ftell( fSrc );
  45.     fseek( fSrc, 0, SEEK_SET );
  46.  
  47.     ogg_sync_state oy;
  48.     ogg_sync_init( &oy );
  49.  
  50.     // read in the entire ogg file and give it to the ogg sync state
  51.     char *pBuffer = ogg_sync_buffer( &oy, oggSizeBytes );
  52.     fread( pBuffer, 1, oggSizeBytes, fSrc );
  53.     ogg_sync_wrote( &oy, oggSizeBytes );
  54.     fclose( fSrc );
  55.  
  56.     // get the first ogg page so we can see what the serial number we need to use is
  57.     ogg_page og;
  58.     ogg_sync_pageout( &oy, &og );
  59.     int serialNumber = ogg_page_serialno( &og );
  60.  
  61.     // set up an ogg stream and load it up with all of the pages we have
  62.     ogg_stream_state os;
  63.     ogg_stream_init( &os, serialNumber );
  64.  
  65.     do
  66.     {
  67.         ogg_stream_pagein( &os, &og );
  68.     }
  69.     while( ogg_sync_pageout( &oy, &og ) > 0 );
  70.  
  71.     // vorbis init
  72.     vorbis_info vi;
  73.     vorbis_info_init( &vi );
  74.  
  75.     vorbis_comment vc;
  76.     vorbis_comment_init( &vc );
  77.  
  78.     vorbis_block vb;
  79.     vorbis_dsp_state vd;
  80.  
  81.     // process all packets
  82.     ogg_packet op;
  83.     int sampleCounter = 0;
  84.     int packetStreamBytes = 0;
  85.     std::vector< StreamMarker > markers;
  86.     std::vector< VorbisPacket > packets;
  87.     while( ogg_stream_packetout( &os, &op ) > 0 )
  88.     {
  89.         // use granulepos from ogg packet to set up stream markers
  90.         // markers are almost 1:1 with ogg but with a slight change on the first audio packet
  91.         int granulePos = -1;
  92.         if( packets.size() == 3 )
  93.         {
  94.             granulePos = 0;
  95.         }
  96.         else if( packets.size() > 3 )
  97.         {
  98.             granulePos = (int)op.granulepos;
  99.         }
  100.  
  101.         if( granulePos >= 0 )
  102.         {
  103.             StreamMarker marker;
  104.             marker.packetStreamByteOffset = packetStreamBytes;
  105.             marker.pcmSampleOffset = granulePos;
  106.             marker.packetIdx = packets.size();
  107.             markers.push_back( marker );
  108.         }
  109.  
  110.         // feed packets to vorbis so we can ask about stream meta data later
  111.         if( packets.size() < 3 )
  112.         {
  113.             vorbis_synthesis_headerin( &vi, &vc, &op );
  114.             if( packets.size() == 2 )
  115.             {
  116.                 vorbis_synthesis_init( &vd, &vi );
  117.                 vorbis_block_init( &vd, &vb );
  118.             }
  119.         }
  120.         else
  121.         {
  122.             vorbis_synthesis( &vb, &op );
  123.             vorbis_synthesis_blockin( &vd, &vb );
  124.  
  125.             float **pcm;
  126.             int samples = vorbis_synthesis_pcmout( &vd, &pcm );
  127.             vorbis_synthesis_read( &vd, samples );
  128.             sampleCounter += samples;
  129.         }
  130.  
  131.         // remember packet data to use later for output
  132.         VorbisPacket packet;
  133.         packet.sizeBytes = op.bytes;
  134.         packet.pData = new unsigned char[ op.bytes ];
  135.         memcpy( packet.pData, op.packet, op.bytes );
  136.         packets.push_back( packet );
  137.  
  138.         packetStreamBytes += sizeof(short) + op.bytes;
  139.     }
  140.  
  141.     // cleanup
  142.     vorbis_block_clear( &vb );
  143.     vorbis_dsp_clear( &vd );   
  144.     vorbis_comment_clear( &vc );
  145.  
  146.     ogg_stream_clear( &os );
  147.     ogg_sync_clear( &oy );
  148.  
  149.     // now we can write the game sound resource output
  150.     FILE *fDest = fopen( "out.o", "wb" );
  151.  
  152.     const int kStdWorkingSetSizeBytes = 108204;
  153.  
  154.     // write header
  155.     SoundHeader hdr;
  156.     hdr.totalSampleCountPerChannel = sampleCounter;
  157.     hdr.vorbisWorkingSetSizeBytes = kStdWorkingSetSizeBytes;
  158.     hdr.vorbisMarkersSizeBytes = markers.size() * sizeof(StreamMarker);
  159.     hdr.vorbisPacketsSizeBytes = packetStreamBytes;
  160.     hdr.oggTotalDataSizeBytes = hdr.vorbisMarkersSizeBytes + hdr.vorbisPacketsSizeBytes;
  161.     hdr.samplesPerSec = vi.rate;
  162.     hdr.channels = vi.channels;
  163.     fwrite( &hdr, 1, sizeof(hdr), fDest );
  164.  
  165.     // write markers
  166.     fwrite( &markers[0], 1, hdr.vorbisMarkersSizeBytes, fDest );
  167.  
  168.     // write packets
  169.     for( unsigned int i=0; i < packets.size(); ++i )
  170.     {
  171.         short packetSizeBytes = packets[i].sizeBytes;
  172.         fwrite( &packetSizeBytes, 1, sizeof(packetSizeBytes), fDest );
  173.         fwrite( packets[i].pData, 1, packets[i].sizeBytes, fDest );
  174.     }
  175.  
  176.     fclose( fDest );
  177.  
  178.     // cleanup
  179.     for( unsigned int i=0; i < packets.size(); ++i )
  180.     {
  181.         delete [] packets[i].pData;
  182.     }
  183.  
  184.     vorbis_info_clear( &vi );
  185.  
  186.     return 0;
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement