I'm trying to read a file containing raw audio and encode it using FLAC. When I run the program, I get a "Bus Error". What could be wrong?
I'm compiling on OS X 10.6.8 using the following line:
gcc nsFlacEncoder.c -I/opt/local/include -lflac -m32 -o flac_enc
#include "FLAC/stream_encoder.h"
#define READSIZE 40000
char buffer[READSIZE];
FLAC__int32 pcm[READSIZE/2];
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data)
{
FILE * fp;
fp = fopen("rec.flac","rw");
fwrite(buffer, 1, bytes, fp);
fclose(fp);
return 0;
}
int rawToFlac()
{
FLAC__bool ok = true;
FLAC__StreamEncoder *encoder = 0;
FLAC__StreamEncoderInitStatus init_status;
unsigned sample_rate = 16000;
unsigned channels = 1;
unsigned bps = 16;
if((encoder=FLAC__stream_encoder_new()) == NULL){
printf("Error!");
return 1;
}
ok &= FLAC__stream_encoder_set_verify(encoder, true);
ok &= FLAC__stream_encoder_set_compression_level(encoder, 5);
ok &= FLAC__stream_encoder_set_channels(encoder, channels);
ok &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
ok &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
ok &= FLAC__stream_encoder_set_total_samples_estimate(encoder, READSIZE);
if(ok){
init_status = FLAC__stream_encoder_init_stream(encoder, &write_callback, NULL, NULL, NULL, /*client_data=*/NULL);
if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK){
printf("Encoder not initiated");
return 1;
}
}
if(ok){
while(ok)
{
/* convert the packed little-endian 16-bit PCM samples from WAVE into an interleaved FLAC__int32 buffer for libFLAC */
size_t i;
for(i = 0; i < 20000; i++) {
/* inefficient but simple and works on big- or little-endian machines */
pcm[i] = (FLAC__int32)(((FLAC__int16)(FLAC__int8)buffer[2*i+1] << 8) | (FLAC__int16)buffer[2*i]);
}
/* feed samples to encoder */
ok = FLAC__stream_encoder_process_interleaved(encoder, pcm, 20000);
}
}
ok &= FLAC__stream_encoder_finish(encoder);
printf("Finished.");
FLAC__stream_encoder_delete(encoder);
return 0;
}
int main()
{
FILE *file;
file = fopen("recording","rb");
fread(buffer,2, 20000, file);
rawToFlac();
fclose(file);
return 0;
}
Running gdb flac_enc
gives me this:
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/bitmath.o" - no debug information available for "bitmath.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/bitreader.o" - no debug information available for "bitreader.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/bitwriter.o" - no debug information available for "bitwriter.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/cpu.o" - no debug information available for "cpu.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/crc.o" - no debug information available for "crc.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/fixed.o" - no debug information available for "fixed.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/format.o" - no debug information available for "format.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/lpc.o" - no debug information available for "lpc.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/md5.o" - no debug information available for "md5.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/memory.o" - no debug information available for "memory.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/metadata_iterators.o" - no debug information available for "metadata_iterators.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/metadata_object.o" - no debug information available for "metadata_object.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/stream_decoder.o" - no debug information available for "stream_decoder.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/stream_encoder.o" - no debug information available for "stream_encoder.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/stream_encoder_framing.o" - no debug information available for "stream_encoder_framing.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/window.o" - no debug information available for "window.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/ogg_decoder_aspect.o" - no debug information available for "ogg_decoder_aspect.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/ogg_encoder_aspect.o" - no debug information available for "ogg_encoder_aspect.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/ogg_helper.o" - no debug information available for "ogg_helper.c".
warning: Could not find object file "/Users/benski/Desktop/flac-1.2.1/src/libFLAC/.libs/ogg_mapping.o" - no debug information available for "ogg_mapping.c".
This is strange since there is no user "benski" on my system. But I'm sure the FLAC libraries are installed properly as the example programs work perfectly.
In main()
, you don't check that the file was opened successfully. The trouble might be that you are using a null pointer in the fread()
operation. Similarly, in the write_callback()
function, your code shows an assumption of invincibility. (Also, if your callback is called more than once, the second call overwrites the data produced by the first call. That, however, is a different problem.)
You don't check how many 2-byte units were read by the fread()
. Nor do you check how much data is written by fwrite()
- was it successful?
You should be able to use gdb
or a similar debugger to see where the fault occurs.
You might be able to use valgrind
to spot the problem too.
You don't need both the if
and the while
in:
if (ok)
{
while (ok)
{
...
}
}
The loop alone is sufficient; it will be executed zero times if ok
is false on the first cycle. If there was a statement after the while
loop and before the end of the if
then both would be necessary.
In general, a SIGBUS (bus error) occurs on RISC chips when you try to access a data object that is misaligned. It is not clear which line could be causing that trouble in this code. Despite the comment about 'null pointer' earlier, that more usually ends up with a SIGSEGV (segmentation violation) than a SIGBUS.