103 lines
3 KiB
C
103 lines
3 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "audio.h"
|
|
#include "audio_internal.h"
|
|
|
|
typedef struct _SourceFileContext {
|
|
AudioBuffer *buffer;
|
|
FILE *fp;
|
|
} SourceFileContext;
|
|
|
|
AudioPipelineStatus source_file_start(AudioPipelineElement *self) {
|
|
SourceFileContext *context = (SourceFileContext *)self->ctx;
|
|
|
|
while(!feof(context->fp)) {
|
|
// fprintf(stderr, "INFO: File offset %d, reading %d\n", ftell(context->fp), context->buffer->buf_size);
|
|
size_t bytes = fread(context->buffer->data, 1, context->buffer->buf_size, context->fp);
|
|
|
|
if (bytes > 0) {
|
|
uint32_t buf_size = context->buffer->buf_size;
|
|
context->buffer->buf_size = (uint32_t)bytes;
|
|
|
|
AudioPipelineStatus result = self->next->push(self->next, context->buffer);
|
|
if ((result != PipelineRunning) && (result != PipelineBuffering)) {
|
|
self->pipeline->status = result;
|
|
if (self->pipeline->statusCallback != NULL) {
|
|
self->pipeline->statusCallback(self->pipeline, result);
|
|
}
|
|
return result;
|
|
}
|
|
context->buffer->buf_size = buf_size;
|
|
}
|
|
}
|
|
|
|
return PipelineFinished;
|
|
}
|
|
|
|
AudioPipelineStatus source_file_reset(AudioPipelineElement *self) {
|
|
SourceFileContext *context = (SourceFileContext *)self->ctx;
|
|
fseek(context->fp, 0, SEEK_SET);
|
|
|
|
return PipelineStopped;
|
|
}
|
|
|
|
char *source_file_describe(AudioPipelineElement *self) {
|
|
return "file source";
|
|
}
|
|
|
|
void source_file_destroy(AudioPipelineElement *self) {
|
|
SourceFileContext *context = (SourceFileContext *)self->ctx;
|
|
free_audio_buffer(context->buffer);
|
|
fclose(context->fp);
|
|
free(self->ctx);
|
|
free(self);
|
|
}
|
|
|
|
AudioPipelineElement *audio_source_file(char *filename, uint32_t block_size) {
|
|
AudioPipelineElement *self = calloc(1, sizeof(AudioPipelineElement));
|
|
if (self == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
SourceFileContext *context = calloc(1, sizeof(SourceFileContext));
|
|
if (context == NULL) {
|
|
free(self);
|
|
return NULL;
|
|
}
|
|
|
|
context->buffer = alloc_audio_buffer(block_size);
|
|
if (context->buffer == NULL) {
|
|
fprintf(stderr, "ERROR: Not enough memory for buffer of size %d!\n", block_size);
|
|
free(context);
|
|
free(self);
|
|
return NULL;
|
|
}
|
|
|
|
context->fp = fopen(filename, "rb");
|
|
if (context->fp == NULL) {
|
|
fprintf(stderr, "ERROR: Could not open file %s\n", filename);
|
|
free_audio_buffer(context->buffer);
|
|
free(context);
|
|
free(self);
|
|
return NULL;
|
|
}
|
|
|
|
self->bits_per_sample = 0;
|
|
self->channels = 0;
|
|
self->sample_rate = 0;
|
|
|
|
self->ctx = context;
|
|
self->describe = source_file_describe;
|
|
self->start = source_file_start;
|
|
self->reset = source_file_reset;
|
|
self->stop = source_stop_nop;
|
|
self->push = NULL;
|
|
self->link = NULL;
|
|
self->destroy = source_file_destroy;
|
|
self->type = AudioElementSource;
|
|
|
|
return self;
|
|
}
|
|
|