Advertisement

Weird C sound library Bug

Started by August 25, 2005 09:34 PM
-1 comments, last by Steve132 19 years, 3 months ago
Hi all.. I have a bizarre bug I am trying to work out: Click here to download full source Hi all who could help me with this: I was trying to create a very small library that could play Ogg Vorbis files cross platform. To do this, I combined the Integer-only C "tremor" ogg decoder library that works exactly like libvorbisfile, and the PortAudio output library. This combination is implemented in a small little file called Portogg.c in the 'src' directory. This compiles and links fine, but on my setup (mingw/w32 on msys), there was a bizarre segmentation fault in the final executable. To run some tests, I reproduced the same code from my test program (main.c) on a lower level by including it all in one file, test_w_saw.c . Weirdly enough, the code runs as intended in test.exe, but not in main.exe. Several runs in debug mode and with gdb have been unhelpful. I realize that this isn't quite NeHe topic, but I like this forum and the people in it. Does anyone out there think they can help? portogg.h

/*standard c header file crap goes here*/
struct port_ogg_sound_s
{
    unsigned char* codedbufferbegin;
    unsigned short codedbufferlength;
    unsigned long  numsamplestotal;
    unsigned long  rate;
    unsigned char  channels;
    short          currvolume;
    PABLIO_Stream          *pa_stream;
    OggVorbis_File          *ovs_file;
    char           is_playing;
};
/*some functions with prefix port_ogg_*/

portogg.c

/*  portogg.c, the source file for portogg, a glue library to play ogg vorbis sounds
    Copyright (C) 2005  Steve*******

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Original Creation DATE: 7/20/05
*/
#include "./portogg.h"

short globalvolume = 32767;
#define MAX_BUFFER 128
char buffer[MAX_BUFFER];

int     port_ogg_load_sound(port_ogg_sound* out_sound,char* filename)
{
    
    PaError         err;
    PABLIO_Stream  *aOutStream;
    OggVorbis_File *vf=(OggVorbis_File *)malloc(sizeof(OggVorbis_File));
    FILE *fi;
    out_sound->ovs_file = vf;
    out_sound->pa_stream = aOutStream;
    fi = fopen(filename,"rb");
    if(!fi)
    {
        return PO_E_FILE_NOT_FOUND;
    }
    if(ov_open(fi,vf,NULL,0) < 0)
    {
        /*error: stream is not an ogg*/
        return PO_E_NOT_OGG;
    }
    ov_comment(vf,-1);
    vorbis_info vfi;
    vfi = *(ov_info(vf,-1));
    
    out_sound->numsamplestotal=(unsigned long)ov_pcm_total(vf,-1);
    ov_comment(vf,-1);
    out_sound->channels = (unsigned char)vfi.channels;
    out_sound->rate     = vfi.rate;
    err = OpenAudioStream( &aOutStream, vfi.rate, paInt16,
                           (PABLIO_WRITE | (vfi.channels >= 2 ? PABLIO_STEREO : PABLIO_MONO)) );
    if( err != paNoError )
    {
        return err;
    }

    return -1;
}
    
    
/*      loads a single ogg vorbis sound into the engine
        Arg1:   the address of a struct to recieve data
        Arg2:   the buffer of compressed data to be played 
        (a memory residing ogg file dump)
        Arg3:   the length of the buffer of compressed data
        returns 0 if error, 1 if none.
*/

char    port_ogg_is_playing(port_ogg_sound* sound)
{
    return (char)sound->is_playing;
}
/*      queries if the ogg vorbis sound is playing
        Arg1:   The sound to query
        returns true if it is playing, false if it isn't playing
*/




int     port_ogg_play_sound(port_ogg_sound* sound)
{
    sound->is_playing=1;
    return 1;
}
/*      instructs the engine to play a sound
        Arg1:`  sound to play
        Arg2:   not required, defaults to false: A flag to play looping?
        Arg3:   not required, defaults to ???:Size of per-callback buffer
*/
int current_section=0;
int     port_ogg_update_sound(port_ogg_sound* sound)
{
    //if(sound->is_playing)
    //{
        int ret=ov_read(sound->ovs_file,buffer,MAX_BUFFER,&current_section);
                /* Write samples to output. */
        WriteAudioStream( sound->pa_stream, buffer, MAX_BUFFER/(sizeof(short)*(sound->channels)) );          
    //}
        
    return 0;
}
/*
    Hands control back to the engine to process a particular sound (not truly multithreaded)
    Arg1:   sound to process
*/

int     port_ogg_stop_sound(port_ogg_sound* sound)
{
    sound->is_playing=0;
    return 1;
}
/*      Insturcts the engine to stop a sound after finishing the buffer
        Arg1:   Sound to stop
*/
int     port_ogg_unload_sound(port_ogg_sound* sound)
{
    PABLIO_Stream *aOutStream;
    OggVorbis_File *vf;
    vf = (OggVorbis_File *)sound->ovs_file;
    aOutStream = (PABLIO_Stream *)sound->pa_stream;
    CloseAudioStream( aOutStream );
    ov_clear(vf);
      return 0;
}
      
/*      collect a sound from memory, stop playing it, and clean it up
        Arg1:   Sound to scrub out
*/

int     port_ogg_global_volume(short v)
{
    globalvolume = (short)((((long)v) * 36737) / 1000);
    return 1;
}
/*      Sets global volume for engine
        Arg1:   number from -1000 to 1000 for volume
*/
int     port_ogg_sound_volume(port_ogg_sound* in_sound,short v)
{
    in_sound->currvolume = (short)((((long)v) * 36737) / 1000);
    return 1;
}

/*      Sets sound volume for a particular stream
        Arg1:  Sound to control
        Arg2:  number from -1000 to 1000 for volume
*/

main.c

#include <stdio.h>
#include <stdlib.h>
#include "inc/portogg.h"

int main(int argc, char *argv[])
{
    port_ogg_sound T;
    printf("sound created\n");
    port_ogg_load_sound(&T,"Fenster.ogg");
    printf("sound loaded\n");
    port_ogg_play_sound(&T);
    printf("sound played\n");
    int i=0;
    while(1)
    {
        //printf("%i: Sound is playing\n",++i);
        port_ogg_update_sound(&T);
    }
    port_ogg_stop_sound(&T);
    printf("sound stopped");
    port_ogg_unload_sound(&T);
  
  system("PAUSE");	
  return 0;
}

test_w_saw.c

/*
 * $Id: test_w_saw.c,v 1.1.1.1.4.1 2003/02/12 02:22:21 philburk Exp $
 * test_w_saw.c
 * Generate stereo sawtooth waveforms.
 *
 * Author: Phil Burk, http://www.softsynth.com
 *
 * This program uses PABLIO, the Portable Audio Blocking I/O Library.
 * PABLIO is built on top of PortAudio, the Portable Audio Library.
 *
 * For more information see: http://www.audiomulch.com/portaudio/
 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files
 * (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software,
 * and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * Any person wishing to distribute modifications to the Software is
 * requested to send the modifications to the original developer so that
 * they can be incorporated into the canonical version.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "src/portaudio/inc/pablio.h"
#include "src/tremor/inc/ivorbiscodec.h"
#include "src/tremor/inc/ivorbisfile.h"
#include <string.h>

#define SAMPLE_RATE         (44100)
#define NUM_SECONDS            (15)
#define SAMPLES_PER_FRAME       (2)

#define FREQUENCY           (220.0f)
#define PHASE_INCREMENT     (2.0f * FREQUENCY / SAMPLE_RATE)
#define FRAMES_PER_BLOCK    (100)

short   samples[FRAMES_PER_BLOCK][SAMPLES_PER_FRAME];
short   phases[SAMPLES_PER_FRAME];

unsigned long ipow(int f)
{
    return (1 << f);
}
    
char* data;
char* datacurs;

/*typedef struct {
  size_t (*read_func)  (void *ptr, size_t size, size_t nmemb, void *datasource);
  int    (*seek_func)  (void *datasource, ogg_int64_t offset, int whence);
  int    (*close_func) (void *datasource);
  long   (*tell_func)  (void *datasource);
} ov_callbacks;*/


/*******************************************************************/
int main(void)
{
    int             i,j;
    PaError         err;
    PABLIO_Stream  *aOutStream;
    OggVorbis_File *vf=(OggVorbis_File *)malloc(sizeof(OggVorbis_File));
    FILE *fi;
    unsigned long BLOCKSIZE=0;
    fi = fopen("Fenster.ogg","rb");
    printf("file loaded\n");
    

    int current_section;
      if(ov_open(fi, vf, NULL, 0) < 0) {
      fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
      exit(1);
  }    
    fprintf(stderr,"hi.  Input buffersize power of 2\n");
    char ss[5];
    BLOCKSIZE = ipow(atoi(gets(ss)));
    char *pcmout = malloc(BLOCKSIZE);
    fprintf(stderr,"\nBuffer is %i bytes\n",BLOCKSIZE);
    char **ptr=ov_comment(vf,-1)->user_comments;
    vorbis_info *vi=ov_info(vf,-1);
    while(*ptr){
      fprintf(stderr,"%s\n",*ptr);
      ++ptr;
    }
    

    printf("Generate sawtooth waves using PABLIO.\n");
    fflush(stdout);
    
        fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate);
    fprintf(stderr,"\nDecoded length: %ld samples\n",
	    (long)ov_pcm_total(vf,-1));
    fprintf(stderr,"Encoded by: %s\n\n",ov_comment(vf,-1)->vendor);

    /* Open simplified blocking I/O layer on top of PortAudio. */
    err = OpenAudioStream( &aOutStream, vi->rate, paInt16,
                           (PABLIO_WRITE | (vi->channels >= 2 ? PABLIO_STEREO : PABLIO_MONO)) );
    if( err != paNoError ) goto error;

    /* Initialize oscillator phases. */
    phases[0] = 0.0;
    phases[1] = 0.0;
    int status;
    int c=0;
    do
    {
        /* Generate sawtooth waveforms in a block for efficiency. */
        status=ov_read(vf,pcmout,BLOCKSIZE,&current_section);
        fprintf(stderr,"b%i:playing\n",++c);
        /* Write samples to output. */
        WriteAudioStream( aOutStream, pcmout, BLOCKSIZE/(sizeof(short)*(vi->channels)) );
    }while(status);

    CloseAudioStream( aOutStream );
    ov_clear(vf);

    printf("Sawtooth sound test complete.\n" );
    fflush(stdout);
    free(pcmout);
    return 0;

error:
    fprintf( stderr, "An error occured while using PABLIO\n" );
    fprintf( stderr, "Error number: %d\n", err );
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
    return -1;
}


This topic is closed to new replies.

Advertisement