Jump to content
  • Advertisement
Sign in to follow this  
Steve132

Weird C sound library Bug

This topic is 4828 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;
}


Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!