Example #1
0
TEST(NeXT, UnspecifiedLength)
{
	std::string testFileName;
	ASSERT_TRUE(createTemporaryFile("NeXT", &testFileName));

	int fd = ::open(testFileName.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);
	ASSERT_GT(fd, -1);
	ASSERT_EQ(::write(fd, kDataUnspecifiedLength, sizeof (kDataUnspecifiedLength)), sizeof (kDataUnspecifiedLength));
	::close(fd);

	AFfilehandle file = afOpenFile(testFileName.c_str(), "r", NULL);
	EXPECT_TRUE(file);

	int sampleFormat, sampleWidth;
	afGetSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);
	EXPECT_TRUE(sampleFormat == AF_SAMPFMT_TWOSCOMP);
	EXPECT_EQ(sampleWidth, 16);
	EXPECT_EQ(afGetChannels(file, AF_DEFAULT_TRACK), 1);
	EXPECT_EQ(afGetTrackBytes(file, AF_DEFAULT_TRACK),
		kFrameCount * sizeof (int16_t));
	EXPECT_EQ(afGetFrameCount(file, AF_DEFAULT_TRACK), kFrameCount);

	int16_t *data = new int16_t[kFrameCount];
	AFframecount framesRead = afReadFrames(file, AF_DEFAULT_TRACK, data,
		kFrameCount);
	EXPECT_EQ(framesRead, kFrameCount);
	for (int i=0; i<kFrameCount; i++)
		EXPECT_EQ(data[i], kFrames[i]);
	delete [] data;

	afCloseFile(file);

	ASSERT_EQ(::unlink(testFileName.c_str()), 0);
}
Example #2
0
void testChannelMatrixReading(int sampleFormat, int sampleWidth)
{
	// Create test file.
	const int channelCount = 2;
	const int frameCount = 10;
	const T samples[channelCount * frameCount] =
	{
		2, 3, 5, 7, 11,
		13, 17, 19, 23, 29,
		31, 37, 41, 43, 47,
		53, 59, 61, 67, 71
	};
	AFfilesetup setup = afNewFileSetup();
	afInitFileFormat(setup, AF_FILE_AIFFC);
	afInitChannels(setup, AF_DEFAULT_TRACK, 2);
	afInitSampleFormat(setup, AF_DEFAULT_TRACK, sampleFormat, sampleWidth);
	AFfilehandle file = afOpenFile(kTestFileName, "w", setup);
	afFreeFileSetup(setup);
	EXPECT_TRUE(file);

	AFframecount framesWritten = afWriteFrames(file, AF_DEFAULT_TRACK,
		samples, frameCount);
	EXPECT_EQ(framesWritten, frameCount);

	EXPECT_EQ(afCloseFile(file), 0);

	// Open file for reading and read data using different channel matrices.
	file = afOpenFile(kTestFileName, "r", NULL);
	EXPECT_TRUE(file);

	EXPECT_EQ(afGetChannels(file, AF_DEFAULT_TRACK), 2);
	EXPECT_EQ(afGetFrameCount(file, AF_DEFAULT_TRACK), frameCount);

	afSetVirtualChannels(file, AF_DEFAULT_TRACK, 1);

	for (int c=0; c<2; c++)
	{
		double channelMatrix[2] = { 0, 0 };
		channelMatrix[c] = 1;
		afSetChannelMatrix(file, AF_DEFAULT_TRACK, channelMatrix);

		EXPECT_EQ(afSeekFrame(file, AF_DEFAULT_TRACK, 0), 0);

		T *readSamples = new T[frameCount]; 
		AFframecount framesRead = afReadFrames(file, AF_DEFAULT_TRACK,
			readSamples, frameCount);
		EXPECT_EQ(framesRead, frameCount);

		for (int i=0; i<frameCount; i++)
			EXPECT_EQ(readSamples[i], samples[2*i + c]);

		delete [] readSamples;
	}

	EXPECT_EQ(afCloseFile(file), 0);

	::unlink(kTestFileName);
}
Example #3
0
static int audiofile_get_duration(const char *file)
{
	int total_time;
	AFfilehandle af_fp = afOpenFile(file, "r", NULL);
	if (af_fp == AF_NULL_FILEHANDLE) {
		return -1;
	}
	total_time = (int)
	    ((double)afGetFrameCount(af_fp, AF_DEFAULT_TRACK)
	     / afGetRate(af_fp, AF_DEFAULT_TRACK));
	afCloseFile(af_fp);
	return total_time;
}
Example #4
0
SoundSample::SoundSample(std::string name, int rev)
{
    uMin = rev;
    samples = NULL;

#ifdef HAVE_AUDIOFILE

    lowPitchOffset = highPitchOffset = 1.0;
    lowVolumeOffset = highVolumeOffset = 1.0;
    lastDir = 0;
    lastValue = 0;
    file = afOpenFile(name.c_str(), "r", 0);
    if (file == AF_NULL_FILEHANDLE)
    {
        QMessageBox::critical(theWindow, "Error",
                              "SoundSample::afOpenFD() - failed!",
                              QMessageBox::Ok,
                              QMessageBox::Ok);
    }
    else
    {
        afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
        //afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, AF_SAMPFMT_FLOAT, 32);

        channels = afGetChannels(file, AF_DEFAULT_TRACK);
        samplesPerSec = (int)afGetRate(file, AF_DEFAULT_TRACK);
        numSamples = afGetFrameCount(file, AF_DEFAULT_TRACK);
        sampleBlocksize = (int)afGetVirtualFrameSize(file, AF_DEFAULT_TRACK, 1);
        bytesPerSample = (int)afGetVirtualFrameSize(file, AF_DEFAULT_TRACK, 1) / channels;
        if (channels != 2)
        {
            std::strstream buf;
            buf << "SoundSample::not a stereo sound file" << name;
            std::string s;
            buf >> s;
            QMessageBox::critical(theWindow, "Error",
                                  s.c_str(),
                                  QMessageBox::Ok,
                                  QMessageBox::Ok);
        }
        if (samplesPerSec != 48000)
        {
            std::strstream buf;
            buf << "SoundSample::48kHz required but " << name << " has " << samplesPerSec;
            std::string s;
            buf >> s;
            QMessageBox::critical(theWindow, "Error",
                                  s.c_str(),
                                  QMessageBox::Ok,
                                  QMessageBox::Ok);
        }
Example #5
0
int
SoundSampleGetData(const char *file, SoundSampleData * ssd)
{
   AFfilehandle        in_file;
   int                 in_format, in_width, bytes_per_frame, frame_count;
   int                 frames_read;

   in_file = afOpenFile(file, "r", NULL);
   if (!in_file)
      return -1;

   frame_count = afGetFrameCount(in_file, AF_DEFAULT_TRACK);
   ssd->channels = afGetChannels(in_file, AF_DEFAULT_TRACK);
   ssd->rate = (unsigned int)(afGetRate(in_file, AF_DEFAULT_TRACK) + .5);
   afGetSampleFormat(in_file, AF_DEFAULT_TRACK, &in_format, &in_width);
   ssd->bit_per_sample = in_width;
#ifdef WORDS_BIGENDIAN
   afSetVirtualByteOrder(in_file, AF_DEFAULT_TRACK, AF_BYTEORDER_BIGENDIAN);
#else
   afSetVirtualByteOrder(in_file, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN);
#endif
   if (EDebug(EDBUG_TYPE_SOUND))
      Eprintf("SoundSampleGetData chan=%d width=%d rate=%d\n", ssd->channels,
	      ssd->bit_per_sample, ssd->rate);

   bytes_per_frame = (ssd->bit_per_sample * ssd->channels) / 8;
   ssd->size = frame_count * bytes_per_frame;
   ssd->data = EMALLOC(unsigned char, ssd->size);

   frames_read =
      afReadFrames(in_file, AF_DEFAULT_TRACK, ssd->data, frame_count);

   afCloseFile(in_file);

   if (frames_read <= 0)
     {
	ssd->size = 0;
	_EFREE(ssd->data);
	return -1;
     }

   return 0;
}
Example #6
0
/*
    0.73s 44100.00 aiff  1ch 16b -- flute.aif
*/
bool printshortinfo (const char *filename)
{
	AFfilehandle file = afOpenFile(filename, "r", NULL);;
	if (!file)
		return false;

	int fileFormat = afGetFileFormat(file, NULL);
	double sampleRate = afGetRate(file, AF_DEFAULT_TRACK);
	double duration = afGetFrameCount(file, AF_DEFAULT_TRACK) / sampleRate;
	const char *labelString =
		(const char *) afQueryPointer(AF_QUERYTYPE_FILEFMT, AF_QUERY_LABEL,
			fileFormat, 0, 0);
	int channels = afGetChannels(file, AF_DEFAULT_TRACK);
	int sampleFormat, sampleWidth;
	afGetSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);

	int compressionType = afGetCompression(file, AF_DEFAULT_TRACK);
	const char *compressionName = "--";
	if (compressionType != AF_COMPRESSION_NONE)
	{
		compressionName =
			(const char *) afQueryPointer(AF_QUERYTYPE_COMPRESSION,
				AF_QUERY_NAME, compressionType, 0, 0);
		if (!compressionName)
			compressionName = "unk";
	}

	printf("%8.2fs %8.2f %4s %2dch %2db %s %s\n",
		duration,
		sampleRate,
		labelString,
		channels,
		sampleWidth,
		compressionName,
		filename);

	afCloseFile(file);

	return true;
}
Example #7
0
//***************************************************************************
bool Kwave::AudiofileDecoder::open(QWidget *widget, QIODevice &src)
{
    metaData().clear();
    Q_ASSERT(!m_source);
    if (m_source) qWarning("AudiofileDecoder::open(), already open !");

    // try to open the source
    if (!src.open(QIODevice::ReadOnly)) {
	qWarning("AudiofileDecoder::open(), failed to open source !");
	return false;
    }

    // source successfully opened
    m_source = &src;
    m_src_adapter = new Kwave::VirtualAudioFile(*m_source);

    Q_ASSERT(m_src_adapter);
    if (!m_src_adapter) return false;

    m_src_adapter->open(m_src_adapter, 0);

    AFfilehandle fh = m_src_adapter->handle();
    if (!fh || (m_src_adapter->lastError() >= 0)) {
	QString reason;

	switch (m_src_adapter->lastError()) {
	    case AF_BAD_NOT_IMPLEMENTED:
	        reason = i18n("Format or function is not implemented");
	        break;
	    case AF_BAD_MALLOC:
	        reason = i18n("Out of memory");
	        break;
	    case AF_BAD_HEADER:
	        reason = i18n("File header is damaged");
	        break;
	    case AF_BAD_CODEC_TYPE:
	        reason = i18n("Invalid codec type");
	        break;
	    case AF_BAD_OPEN:
	        reason = i18n("Opening the file failed");
	        break;
	    case AF_BAD_READ:
	        reason = i18n("Read access failed");
	        break;
	    case AF_BAD_SAMPFMT:
	        reason = i18n("Invalid sample format");
	        break;
	    default:
		reason = reason.number(m_src_adapter->lastError());
	}

	QString text= i18n("An error occurred while opening the "\
	    "file:\n'%1'", reason);
	Kwave::MessageBox::error(widget, text);

	return false;
    }

    AFframecount length = afGetFrameCount(fh, AF_DEFAULT_TRACK);
    unsigned int tracks = qMax(afGetVirtualChannels(fh, AF_DEFAULT_TRACK), 0);
    unsigned int bits = 0;
    double       rate = 0.0;
    int af_sample_format;
    afGetVirtualSampleFormat(fh, AF_DEFAULT_TRACK, &af_sample_format,
	reinterpret_cast<int *>(&bits));
    Kwave::SampleFormat::Format fmt;
    switch (af_sample_format)
    {
	case AF_SAMPFMT_TWOSCOMP:
	    fmt = Kwave::SampleFormat::Signed;
	    break;
	case AF_SAMPFMT_UNSIGNED:
	    fmt = Kwave::SampleFormat::Unsigned;
	    break;
	case AF_SAMPFMT_FLOAT:
	    fmt = Kwave::SampleFormat::Float;
	    break;
	case AF_SAMPFMT_DOUBLE:
	    fmt = Kwave::SampleFormat::Double;
	    break;
	default:
	    fmt = Kwave::SampleFormat::Unknown;
	    break;
    }

    // get sample rate, with fallback to 8kHz
    rate = afGetRate(fh, AF_DEFAULT_TRACK);
    if (rate < 1.0) {
	qWarning("\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"\
	         "WARNING: file has no sample rate!\n"\
	         "         => using 8000 samples/sec as fallback\n"\
	         "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
	rate = 8000.0;
    }

    Kwave::SampleFormat::Map sf;
    QString sample_format_name = sf.description(Kwave::SampleFormat(fmt), true);

    if (static_cast<signed int>(bits) < 0) bits = 0;

    int af_compression = afGetCompression(fh, AF_DEFAULT_TRACK);
    const Kwave::Compression compression(
	Kwave::Compression::fromAudiofile(af_compression)
    );

    Kwave::FileInfo info(metaData());
    info.setRate(rate);
    info.setBits(bits);
    info.setTracks(tracks);
    info.setLength(length);
    info.set(INF_SAMPLE_FORMAT, Kwave::SampleFormat(fmt).toInt());
    info.set(Kwave::INF_COMPRESSION, compression.toInt());
    metaData().replace(Kwave::MetaDataList(info));
    qDebug("-------------------------");
    qDebug("info:");
    qDebug("compression = %d", af_compression);
    qDebug("channels    = %d", info.tracks());
    qDebug("rate        = %0.0f", info.rate());
    qDebug("bits/sample = %d", info.bits());
    qDebug("length      = %lu samples",
	   static_cast<unsigned long int>(info.length()));
    qDebug("format      = %d (%s)", af_sample_format,
                                    DBG(sample_format_name));
    qDebug("-------------------------");

    // set up libaudiofile to produce Kwave's internal sample format
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
    afSetVirtualByteOrder(fh, AF_DEFAULT_TRACK, AF_BYTEORDER_BIGENDIAN);
#else
    afSetVirtualByteOrder(fh, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN);
#endif
    afSetVirtualSampleFormat(fh, AF_DEFAULT_TRACK,
	AF_SAMPFMT_TWOSCOMP, SAMPLE_STORAGE_BITS);

    return true;
}
Example #8
0
int main (int argc, char **argv)
{
	int	i = 1;
	char	*infilename, *outfilename;
	int	fileFormat, outFileFormat = AF_FILE_UNKNOWN;

	AFfilehandle	infile, outfile;
	AFfilesetup	outfilesetup;
	int		sampleFormat, sampleWidth, channelCount;
	double		sampleRate;
	int		outSampleFormat = -1, outSampleWidth = -1,
			outChannelCount = -1;
	double		outMaxAmp = 1.0;

	AFframecount	totalFrames;

	if (argc == 2)
	{
		if (!strcmp(argv[1], "--version") || !strcmp(argv[1], "-v"))
		{
			printversion();
			exit(EXIT_SUCCESS);
		}

		if (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))
		{
			printusage();
			exit(EXIT_SUCCESS);
		}
	}

	if (argc < 3)
		usageerror();

	infilename = argv[1];
	outfilename = argv[2];

	i = 3;

	while (i < argc)
	{
		if (!strcmp(argv[i], "format"))
		{
			if (i + 1 >= argc)
				usageerror();
			if (!strcmp(argv[i+1], "aiff"))
				outFileFormat = AF_FILE_AIFF;
			else if (!strcmp(argv[i+1], "aifc"))
				outFileFormat = AF_FILE_AIFFC;
			else if (!strcmp(argv[i+1], "wave"))
				outFileFormat = AF_FILE_WAVE;
			else if (!strcmp(argv[i+1], "next"))
				outFileFormat = AF_FILE_NEXTSND;
			else if (!strcmp(argv[i+1], "bics"))
				outFileFormat = AF_FILE_BICSF;
			else if (!strcmp(argv[i+1], "voc"))
				outFileFormat = AF_FILE_VOC;
			else if (!strcmp(argv[i+1], "nist"))
				outFileFormat = AF_FILE_NIST_SPHERE;
			else if (!strcmp(argv[i+1], "caf"))
				outFileFormat = AF_FILE_CAF;
			else
			{
				fprintf(stderr, "sfconvert: Unknown format %s.\n", argv[i+1]);
				exit(EXIT_FAILURE);
			}

			/* Increment for argument. */
			i++;
		}
		else if (!strcmp(argv[i], "channels"))
		{
			if (i + 1 >= argc)
				usageerror();

			outChannelCount = atoi(argv[i+1]);
			if (outChannelCount < 1)
				usageerror();

			/* Increment for argument. */
			i++;
		}
		else if (!strcmp(argv[i], "float"))
		{
			if (i + 1 >= argc)
				usageerror();

			outSampleFormat = AF_SAMPFMT_FLOAT;
			outSampleWidth = 32;
			outMaxAmp = atof(argv[i+1]);

			/* Increment for argument. */
			i++;
		}
		else if (!strcmp(argv[i], "integer"))
		{
			if (i + 2 >= argc)
				usageerror();

			outSampleWidth = atoi(argv[i+1]);
			if (outSampleWidth < 1 || outSampleWidth > 32)
				usageerror();

			if (!strcmp(argv[i+2], "2scomp"))
				outSampleFormat = AF_SAMPFMT_TWOSCOMP;
			else if (!strcmp(argv[i+2], "unsigned"))
				outSampleFormat = AF_SAMPFMT_UNSIGNED;
			else
				usageerror();

			/* Increment for arguments. */
			i += 2;
		}
		else
		{
			printf("Unrecognized command %s\n", argv[i]);
		}

		i++;
	}

	infile = afOpenFile(infilename, "r", AF_NULL_FILESETUP);
	if (infile == AF_NULL_FILEHANDLE)
	{
		printf("Could not open file '%s' for reading.\n", infilename);
		return 1;
	}

	/* Get audio format parameters from input file. */
	fileFormat = afGetFileFormat(infile, NULL);
	totalFrames = afGetFrameCount(infile, AF_DEFAULT_TRACK);
	channelCount = afGetChannels(infile, AF_DEFAULT_TRACK);
	sampleRate = afGetRate(infile, AF_DEFAULT_TRACK);
	afGetSampleFormat(infile, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);

	/* Initialize output audio format parameters. */
	outfilesetup = afNewFileSetup();

	if (outFileFormat == -1)
		outFileFormat = fileFormat;

	if (outSampleFormat == -1 || outSampleWidth == -1)
	{
		outSampleFormat = sampleFormat;
		outSampleWidth = sampleWidth;
	}

	if (outChannelCount == -1)
		outChannelCount = channelCount;

	afInitFileFormat(outfilesetup, outFileFormat);
	afInitSampleFormat(outfilesetup, AF_DEFAULT_TRACK, outSampleFormat,
		outSampleWidth);
	afInitChannels(outfilesetup, AF_DEFAULT_TRACK, outChannelCount);
	afInitRate(outfilesetup, AF_DEFAULT_TRACK, sampleRate);

	outfile = afOpenFile(outfilename, "w", outfilesetup);
	if (outfile == AF_NULL_FILEHANDLE)
	{
		printf("Could not open file '%s' for writing.\n", outfilename);
		return 1;
	}

	/*
		Set the output file's virtual audio format parameters
		to match the audio format parameters of the input file.
	*/
	afSetVirtualChannels(outfile, AF_DEFAULT_TRACK, channelCount);
	afSetVirtualSampleFormat(outfile, AF_DEFAULT_TRACK, sampleFormat,
		sampleWidth);

	afFreeFileSetup(outfilesetup);

	copyaudiodata(infile, outfile, AF_DEFAULT_TRACK, totalFrames);

	afCloseFile(infile);
	afCloseFile(outfile);

	printfileinfo(infilename);
	putchar('\n');
	printfileinfo(outfilename);

	return EXIT_SUCCESS;
}
static void
audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
{
	GError *error = NULL;
	AFvirtualfile *vf;
	int fs, frame_count;
	AFfilehandle af_fp;
	struct audio_format audio_format;
	float total_time;
	uint16_t bit_rate;
	int ret;
	char chunk[CHUNK_SIZE];
	enum decoder_command cmd;

	if (!is->seekable) {
		g_warning("not seekable");
		return;
	}

	vf = setup_virtual_fops(is);

	af_fp = afOpenVirtualFile(vf, "r", NULL);
	if (af_fp == AF_NULL_FILEHANDLE) {
		g_warning("failed to input stream\n");
		return;
	}

	if (!audio_format_init_checked(&audio_format,
				       afGetRate(af_fp, AF_DEFAULT_TRACK),
				       audiofile_setup_sample_format(af_fp),
				       afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK),
				       &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		afCloseFile(af_fp);
		return;
	}

	frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);

	total_time = ((float)frame_count / (float)audio_format.sample_rate);

	bit_rate = (uint16_t)(is->size * 8.0 / total_time / 1000.0 + 0.5);

	fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);

	decoder_initialized(decoder, &audio_format, true, total_time);

	do {
		ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
				   CHUNK_SIZE / fs);
		if (ret <= 0)
			break;

		cmd = decoder_data(decoder, NULL,
				   chunk, ret * fs,
				   bit_rate);

		if (cmd == DECODE_COMMAND_SEEK) {
			AFframecount frame = decoder_seek_where(decoder) *
				audio_format.sample_rate;
			afSeekFrame(af_fp, AF_DEFAULT_TRACK, frame);

			decoder_command_finished(decoder);
			cmd = DECODE_COMMAND_NONE;
		}
	} while (cmd == DECODE_COMMAND_NONE);

	afCloseFile(af_fp);
}
Example #10
0
void testalaw (int fileFormat)
{
	AFfilehandle	file;
	AFfilesetup	setup;
	uint16_t	samples[] = {8, 24, 88, 120, 184, 784, 912, 976,
                        1120, 1440, 1888, 8960, 9984, 16128, 19968, 32256};
	uint16_t	readsamples[SAMPLE_COUNT];
	AFframecount	framesWritten, framesRead;
	int		i;

	setup = afNewFileSetup();

	afInitCompression(setup, AF_DEFAULT_TRACK, AF_COMPRESSION_G711_ALAW);
	afInitFileFormat(setup, fileFormat);
	afInitChannels(setup, AF_DEFAULT_TRACK, 1);

	file = afOpenFile(TEST_FILE, "w", setup);
	afFreeFileSetup(setup);

	ensure(afGetCompression(file, AF_DEFAULT_TRACK) ==
		AF_COMPRESSION_G711_ALAW,
		"test file not created with G.711 A-law compression");

	ensure(file != AF_NULL_FILEHANDLE, "unable to open file for writing");

	framesWritten = afWriteFrames(file, AF_DEFAULT_TRACK, samples,
		FRAME_COUNT);

	ensure(framesWritten == FRAME_COUNT,
		"number of frames requested does not match number of frames written");
	afCloseFile(file);

	/* Open the file for reading and verify the data. */
	file = afOpenFile(TEST_FILE, "r", NULL);
	ensure(file != AF_NULL_FILEHANDLE, "unable to open file for reading");

	ensure(afGetFileFormat(file, NULL) == fileFormat,
		"test file format incorrect");

	ensure(afGetCompression(file, AF_DEFAULT_TRACK) ==
		AF_COMPRESSION_G711_ALAW,
		"test file not opened with G.711 A-law compression");

	framesRead = afReadFrames(file, AF_DEFAULT_TRACK, readsamples,
		FRAME_COUNT);

	ensure(framesRead == FRAME_COUNT,
		"number of frames read does not match number of frames requested");

#ifdef DEBUG
	for (i=0; i<SAMPLE_COUNT; i++)
		printf("readsamples[%d]: %d\n", i, readsamples[i]);
	for (i=0; i<SAMPLE_COUNT; i++)
		printf("samples[%d]: %d\n", i, samples[i]);
#endif

	for (i=0; i<SAMPLE_COUNT; i++)
	{
		ensure(samples[i] == readsamples[i],
			"data written does not match data read");
	}

	/* G.711 compression uses one byte per sample. */
	ensure(afGetTrackBytes(file, AF_DEFAULT_TRACK) == SAMPLE_COUNT,
		"track byte count is incorrect");

	ensure(afGetFrameCount(file, AF_DEFAULT_TRACK) == FRAME_COUNT,
		"frame count is incorrect");

	ensure(afGetChannels(file, AF_DEFAULT_TRACK) == 1,
		"channel count is incorrect");

	ensure(afCloseFile(file) == 0, "error closing file");

	cleanup();
}
Example #11
0
libspectrum_error
libspectrum_wav_read( libspectrum_tape *tape, const char *filename )
{
  libspectrum_byte *buffer; size_t length;
  libspectrum_byte *tape_buffer; size_t tape_length;
  size_t data_length;
  libspectrum_tape_block *block = NULL;
  int frames;

  /* Our filehandle from libaudiofile */
  AFfilehandle handle;

  /* The track we're using in the file */
  int track = AF_DEFAULT_TRACK; 

  if( !filename ) {
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: no filename provided - wav files can only be loaded from a file"
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  handle = afOpenFile( filename, "r", NULL );
  if( handle == AF_NULL_FILEHANDLE ) {
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: audiofile failed to open file:%s", filename
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  if( afSetVirtualSampleFormat( handle, track, AF_SAMPFMT_UNSIGNED, 8 ) ) {
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: audiofile failed to set virtual sample format"
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  if( afSetVirtualChannels( handle, track, 1 ) ) {
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_LOGIC,
      "libspectrum_wav_read: audiofile failed to set virtual channel count"
    );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  length = afGetFrameCount( handle, track );

  tape_length = length;
  if( tape_length%8 ) tape_length += 8 - (tape_length%8);

  buffer = libspectrum_new0( libspectrum_byte,
			     tape_length * afGetChannels(handle, track) );

  frames = afReadFrames( handle, track, buffer, length );
  if( frames == -1 ) {
    libspectrum_free( buffer );
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_wav_read: can't calculate number of frames in audio file"
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  if( !length ) {
    libspectrum_free( buffer );
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_wav_read: empty audio file, nothing to load"
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  if( frames != length ) {
    libspectrum_free( buffer );
    afCloseFile( handle );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_CORRUPT,
      "libspectrum_wav_read: read %d frames, but expected %lu\n", frames,
      (unsigned long)length
    );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  block = libspectrum_tape_block_alloc( LIBSPECTRUM_TAPE_BLOCK_RAW_DATA );

  /* 44100 Hz 79 t-states 22050 Hz 158 t-states */
  libspectrum_tape_block_set_bit_length( block,
                                         3500000/afGetRate( handle, track ) );
  libspectrum_set_pause_ms( block, 0 );
  libspectrum_tape_block_set_bits_in_last_byte( block,
              length % LIBSPECTRUM_BITS_IN_BYTE ?
                length % LIBSPECTRUM_BITS_IN_BYTE : LIBSPECTRUM_BITS_IN_BYTE );
  data_length = tape_length / LIBSPECTRUM_BITS_IN_BYTE;
  libspectrum_tape_block_set_data_length( block, data_length );

  tape_buffer = libspectrum_new0( libspectrum_byte, data_length );

  libspectrum_byte *from = buffer;
  libspectrum_byte *to = tape_buffer;
  length = tape_length;
  do {
    libspectrum_byte val = 0;
    int i;
    for( i = 7; i >= 0; i-- ) {
      if( *from++ > 127 ) val |= 1 << i;
    }
    *to++ = val;
  } while ((length -= 8) > 0);

  libspectrum_tape_block_set_data( block, tape_buffer );

  libspectrum_tape_append_block( tape, block );

  if( afCloseFile( handle ) ) {
    libspectrum_free( buffer );
    libspectrum_print_error(
      LIBSPECTRUM_ERROR_UNKNOWN,
      "libspectrum_wav_read: failed to close audio file"
    );
    return LIBSPECTRUM_ERROR_UNKNOWN;
  }

  libspectrum_free( buffer );

  /* Successful completion */
  return LIBSPECTRUM_ERROR_NONE;
}
Example #12
0
static void testADPCM(int fileFormat, int compressionFormat, int channelCount,
	int bytesPerPacket, int framesPerPacket, int frameCount, int threshold)
{
	std::string testFileName;
	ASSERT_TRUE(createTemporaryFile("ADPCM", &testFileName));

	AFfilesetup setup = afNewFileSetup();
	afInitFileFormat(setup, fileFormat);
	afInitChannels(setup, AF_DEFAULT_TRACK, channelCount);
	afInitCompression(setup, AF_DEFAULT_TRACK, compressionFormat);
	AFfilehandle file = afOpenFile(testFileName.c_str(), "w", setup);
	ASSERT_TRUE(file);
	afFreeFileSetup(setup);

	int16_t *data = new int16_t[frameCount * channelCount];
	for (int i=0; i<frameCount; i++)
		for (int c=0; c<channelCount; c++)
			data[i*channelCount + c] = i * ((c&1) ? -1 : 1);
	
	AFframecount framesWritten = afWriteFrames(file, AF_DEFAULT_TRACK, data, frameCount);
	ASSERT_EQ(framesWritten, frameCount);

	ASSERT_EQ(afCloseFile(file), 0);

	file = afOpenFile(testFileName.c_str(), "r", AF_NULL_FILESETUP);
	ASSERT_TRUE(file);
	ASSERT_EQ(afGetCompression(file, AF_DEFAULT_TRACK), compressionFormat);
	ASSERT_EQ(afGetFrameCount(file, AF_DEFAULT_TRACK), frameCount);
	ASSERT_EQ(afGetTrackBytes(file, AF_DEFAULT_TRACK),
		(bytesPerPacket * frameCount) / framesPerPacket);

	int16_t *readData = new int16_t[frameCount * channelCount];
	AFframecount framesRead = afReadFrames(file, AF_DEFAULT_TRACK, readData, frameCount);
	ASSERT_EQ(framesRead, frameCount);

	for (int i=0; i<frameCount; i++)
		for (int c=0; c<channelCount; c++)
			EXPECT_LE(std::abs(data[i*channelCount + c] - readData[i*channelCount + c]), threshold);

	int16_t *offsetReadData = new int16_t[frameCount * channelCount];

	// Read entire file with a seek before each read operation.
	for (AFframecount offset = 0; offset < frameCount; offset += framesPerPacket + 3)
	{
		ASSERT_EQ(afSeekFrame(file, AF_DEFAULT_TRACK, offset), offset);

		AFframecount framesToRead = 1091;
		framesRead = afReadFrames(file, AF_DEFAULT_TRACK, offsetReadData, framesToRead);
		ASSERT_EQ(framesRead, std::min(framesToRead, frameCount - offset));

		for (int i=0; i<framesRead; i++)
			for (int c=0; c<channelCount; c++)
				EXPECT_EQ(readData[(i+offset)*channelCount + c],
					offsetReadData[i*channelCount + c]);
	}

	// Read entire file sequentially in multiple read operations.
	ASSERT_EQ(afSeekFrame(file, AF_DEFAULT_TRACK, 0), 0);

	AFframecount framesToRead = 1087;
	for (AFframecount offset = 0; offset < frameCount; offset += framesToRead)
	{
		framesRead = afReadFrames(file, AF_DEFAULT_TRACK, offsetReadData, framesToRead);
		ASSERT_EQ(framesRead, std::min(framesToRead, frameCount - offset));

		for (int i=0; i<framesRead; i++)
			for (int c=0; c<channelCount; c++)
				EXPECT_EQ(readData[(i+offset)*channelCount + c],
					offsetReadData[i*channelCount + c]);
	}

	ASSERT_EQ(afCloseFile(file), 0);

	delete [] data;
	delete [] readData;
	delete [] offsetReadData;

	ASSERT_EQ(::unlink(testFileName.c_str()), 0);
}
Example #13
0
static void
audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
{
	AFvirtualfile *vf;
	int fs, frame_count;
	AFfilehandle af_fp;
	int bits;
	struct audio_format audio_format;
	float total_time;
	uint16_t bit_rate;
	int ret, current = 0;
	char chunk[CHUNK_SIZE];
	enum decoder_command cmd;

	if (!is->seekable) {
		g_warning("not seekable");
		return;
	}

	vf = setup_virtual_fops(is);

	af_fp = afOpenVirtualFile(vf, "r", NULL);
	if (af_fp == AF_NULL_FILEHANDLE) {
		g_warning("failed to input stream\n");
		return;
	}

	afGetSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
	if (!audio_valid_sample_format(bits)) {
		g_debug("input file has %d bit samples, converting to 16",
			bits);
		bits = 16;
	}

	afSetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK,
	                         AF_SAMPFMT_TWOSCOMP, bits);
	afGetVirtualSampleFormat(af_fp, AF_DEFAULT_TRACK, &fs, &bits);
	audio_format.bits = (uint8_t)bits;
	audio_format.sample_rate =
	                      (unsigned int)afGetRate(af_fp, AF_DEFAULT_TRACK);
	audio_format.channels =
	              (uint8_t)afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK);

	if (!audio_format_valid(&audio_format)) {
		g_warning("Invalid audio format: %u:%u:%u\n",
			  audio_format.sample_rate, audio_format.bits,
			  audio_format.channels);
		afCloseFile(af_fp);
		return;
	}

	frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);

	total_time = ((float)frame_count / (float)audio_format.sample_rate);

	bit_rate = (uint16_t)(is->size * 8.0 / total_time / 1000.0 + 0.5);

	fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);

	decoder_initialized(decoder, &audio_format, true, total_time);

	do {
		ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
				   CHUNK_SIZE / fs);
		if (ret <= 0)
			break;

		current += ret;
		cmd = decoder_data(decoder, NULL,
				   chunk, ret * fs,
				   (float)current /
				   (float)audio_format.sample_rate,
				   bit_rate, NULL);

		if (cmd == DECODE_COMMAND_SEEK) {
			current = decoder_seek_where(decoder) *
				audio_format.sample_rate;
			afSeekFrame(af_fp, AF_DEFAULT_TRACK, current);

			decoder_command_finished(decoder);
			cmd = DECODE_COMMAND_NONE;
		}
	} while (cmd == DECODE_COMMAND_NONE);

	afCloseFile(af_fp);
}
Example #14
0
VeSound *veSoundLoadFile_AudioFile(char *file) {
  AFfilehandle fh;
  VeSound *snd;
  int nchan, nframe;
  int fsz, i, n;
  float *buf;
  
  if (!(fh = afOpenFile(file,"r",0))) {
    veError(MODULE,"audiofile library could not open sound file '%s'",
	    file);
    return NULL;
  }
  afSetVirtualSampleFormat(fh,AF_DEFAULT_TRACK,AF_SAMPFMT_FLOAT,4);
  // Hack. 
  // afSetVirtualRate(fh,AF_DEFAULT_TRACK,(double)veAudioGetSampFreq());
  nchan = afGetChannels(fh,AF_DEFAULT_TRACK);
  if (nchan < 1) {
    veError(MODULE,"sound file has no tracks?");
    afCloseFile(fh);
    return NULL;
  }
  if (nchan > 2) {
    veError(MODULE,"sound file has more than 2 tracks - rejecting it");
    afCloseFile(fh);
    return NULL;
  }
  nframe = afGetFrameCount(fh,AF_DEFAULT_TRACK);
  fsz = veAudioGetFrameSize();

  snd = veAllocObj(VeSound);
  snd->nframes = nframe/fsz;
  if (n % fsz)
    snd->nframes++;
  snd->data = veAlloc(snd->nframes*sizeof(float)*fsz,0);
  buf = veAlloc(2*fsz*sizeof(float),0);

  for (i = 0; i < snd->nframes; i++) {
    memset(buf,0,fsz*sizeof(float)); /* zero buffer */
    n = afReadFrames(fh,AF_DEFAULT_TRACK,buf,fsz);
    if (n == -1) {
      veError(MODULE,"sound file read failed for '%s': %s",
	      file, strerror(errno));
      afCloseFile(fh);
      veFree(buf);
      veFree(snd->data);
      veFree(snd);
      return NULL;
    }
    if (nchan == 1)
      /* remember: snd->data is a (float *) */
      memcpy(snd->data+fsz*i,buf,fsz*sizeof(float));
    else {
      /* downmix stereo to mono (trivial) */
      int k;
      for (k = 0; k < fsz; k++)
	snd->data[fsz*i+k] = (buf[2*k] + buf[2*k+1])/2.0;
    }
  }

  afCloseFile(fh);
  veFree(buf);

  snd->file = veDupString(file);
  /* initialize other fields */
  snd->id = -1;
  snd->name = NULL;

  return snd;
}
Example #15
0
bool printfileinfo (const char *filename)
{
	AFfilehandle file = afOpenFile(filename, "r", NULL);
	if (!file)
		return false;

	int fileFormat = afGetFileFormat(file, NULL);
	const char *formatstring =
		(const char *) afQueryPointer(AF_QUERYTYPE_FILEFMT, AF_QUERY_DESC,
			fileFormat, 0, 0);
	const char *labelstring =
		(const char *) afQueryPointer(AF_QUERYTYPE_FILEFMT, AF_QUERY_LABEL,
			fileFormat, 0, 0);

	if (!formatstring || !labelstring)
		return false;

	printf("File Name      %s\n", filename);
	printf("File Format    %s (%s)\n", formatstring, labelstring);

	int sampleFormat, sampleWidth;
	afGetSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);

	int byteOrder = afGetByteOrder(file, AF_DEFAULT_TRACK);

	printf("Data Format    ");

	int compressionType = afGetCompression(file, AF_DEFAULT_TRACK);
	if (compressionType == AF_COMPRESSION_NONE)
	{
		switch (sampleFormat)
		{
			case AF_SAMPFMT_TWOSCOMP:
				printf("%d-bit integer (2's complement, %s)",
					sampleWidth,
					byteOrder == AF_BYTEORDER_BIGENDIAN ?
						"big endian" : "little endian");
				break;
			case AF_SAMPFMT_UNSIGNED:
				printf("%d-bit integer (unsigned, %s)",
					sampleWidth,
					byteOrder == AF_BYTEORDER_BIGENDIAN ?
						"big endian" : "little endian");
				break;
			case AF_SAMPFMT_FLOAT:
				printf("single-precision (32-bit) floating point, %s",
					byteOrder == AF_BYTEORDER_BIGENDIAN ?
						"big endian" : "little endian");
				break;
			case AF_SAMPFMT_DOUBLE:
				printf("double-precision (64-bit) floating point, %s",
					byteOrder == AF_BYTEORDER_BIGENDIAN ?
						"big endian" : "little endian");
				break;
			default:
				printf("unknown");
				break;
		}
	}
	else
	{
		const char *compressionName =
			(const char *) afQueryPointer(AF_QUERYTYPE_COMPRESSION,
				AF_QUERY_NAME, compressionType, 0, 0);

		if (!compressionName)
			printf("unknown compression");
		else
			printf("%s compression", compressionName);
	}
	printf("\n");

	printf("Audio Data     %jd bytes begins at offset %jd (%jx hex)\n",
		(intmax_t) afGetTrackBytes(file, AF_DEFAULT_TRACK),
		(intmax_t) afGetDataOffset(file, AF_DEFAULT_TRACK),
		(uintmax_t) afGetDataOffset(file, AF_DEFAULT_TRACK));

	printf("               %d channel%s, %jd frames\n",
		afGetChannels(file, AF_DEFAULT_TRACK),
		afGetChannels(file, AF_DEFAULT_TRACK) > 1 ? "s" : "",
		(intmax_t) afGetFrameCount(file, AF_DEFAULT_TRACK));

	printf("Sampling Rate  %.2f Hz\n", afGetRate(file, AF_DEFAULT_TRACK));

	printf("Duration       %.3f seconds\n",
		afGetFrameCount(file, AF_DEFAULT_TRACK) /
		afGetRate(file, AF_DEFAULT_TRACK));

	char *copyright = copyrightstring(file);
	if (copyright)
	{
		printf("Copyright      %s\n", copyright);
		free(copyright);
	}

	afCloseFile(file);

	return true;
}
Example #16
0
static int audiofile_get_total_len(struct audiotap *audiotap){
  return (int)(afGetFrameCount((AFfilehandle)audiotap->priv, AF_DEFAULT_TRACK));
}
Example #17
0
void print_power (char *filename)
{
	AFfilehandle	file;
	double		*sums, *frames;
	int		channelCount, windowSize, frameCount;
	int		i, c;
	struct smooth	*powsmooth;
	int		winStart, winEnd;
	int		lastWindow = FALSE;
	double		pow, maxpow;

	double		level, peak, minSample = 1, maxSample = -1;

	file = afOpenFile(filename, "r", NULL);
	if (file == AF_NULL_FILEHANDLE)
	{
		fprintf(stderr, "Could not open file %s.\n", filename);
		return;
	}

	channelCount = afGetChannels(file, AF_DEFAULT_TRACK);
	windowSize = afGetRate(file, AF_DEFAULT_TRACK) / 100;
	frameCount = afGetFrameCount(file, AF_DEFAULT_TRACK);

	sums = calloc(channelCount, sizeof (double));
	for (c=0; c<channelCount; c++)
		sums[c] = 0;

	frames = calloc(channelCount * windowSize, sizeof (double));

	afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, AF_SAMPFMT_DOUBLE,
		sizeof (double));

	powsmooth = calloc(channelCount, sizeof (struct smooth));
	for (c=0; c<channelCount; c++)
	{
		/* Use a 100-element (1 second) window. */
		powsmooth[c].length = 100;
		powsmooth[c].buf = calloc(powsmooth[c].length, sizeof (double));
		powsmooth[c].start = 0;
		powsmooth[c].n = 0;
	}

	winStart = 0;
	winEnd = 0;
	lastWindow = FALSE;
	maxpow = 0;

	do
	{
		winEnd = winStart + windowSize;

		if (winEnd >= frameCount)
		{
			winEnd = frameCount;
			lastWindow = TRUE;
		}

		afReadFrames(file, AF_DEFAULT_TRACK, frames, windowSize);

		for (c=0; c<channelCount; c++)
		{
			sums[c] = 0;

			for (i=0; i < winEnd - winStart; i++)
			{
				double	sample;

				sample = frames[i*channelCount + c];
				sums[c] += sample*sample;

				if (sample > maxSample)
					maxSample = sample;
				if (sample < minSample)
					minSample = sample;
			}
		}

		/* Compute power for each channel. */
		for (c=0; c<channelCount; c++)
		{
			double pow;
			int end;

			pow = sums[c] / (winEnd - winStart);

			end = (powsmooth[c].start + powsmooth[c].n) %
				powsmooth[c].length;
			powsmooth[c].buf[end] = pow;

			if (powsmooth[c].n == powsmooth[c].length)
			{
				powsmooth[c].start = (powsmooth[c].start + 1) % powsmooth[c].length;
				pow = get_smoothed_data(&powsmooth[c]);
				if (pow > maxpow)
					maxpow = pow;
			}
			else
			{
				powsmooth[c].n++;
			}
		}

		winStart += windowSize;
	} while (!lastWindow);

	for (c = 0; c < channelCount; c++)
	{
		pow = get_smoothed_data(&powsmooth[c]);
		if (pow > maxpow)
			maxpow = pow;
	}

	free(sums);
	free(frames);
	for (c=0; c<channelCount; c++)
		free(powsmooth[c].buf);
	free(powsmooth);

	level = sqrt(maxpow);

	afCloseFile(file);

	printf("file: %s\n", filename);

	printf("level (dB): %f\n", 20 * log10(level));
	printf("peak-: %f\n", minSample);
	printf("peak+: %f\n", maxSample);

	peak = abs(minSample);
	if (peak < abs(maxSample))
		peak = abs(maxSample);

	printf("peak (dB): %f\n", 20 * log10(peak));
}
Example #18
0
main (int argc, char **argv)
{
	AFfilehandle	file;
	AFframecount	count, frameCount;
	int		channelCount, sampleFormat, sampleWidth;
	float		frameSize;
	void		*buffer;
	double		sampleRate;

	ALport		outport;
	ALconfig	outportconfig;

	if (argc < 2)
		usage();

	file = afOpenFile(argv[1], "r", NULL);
	if (file == AF_NULL_FILEHANDLE)
	{
		fprintf(stderr, "Could not open file %s.\n", argv[1]);
		exit(EXIT_FAILURE);
	}

	frameCount = afGetFrameCount(file, AF_DEFAULT_TRACK);
	frameSize = afGetVirtualFrameSize(file, AF_DEFAULT_TRACK, 1);
	channelCount = afGetVirtualChannels(file, AF_DEFAULT_TRACK);
	sampleRate = afGetRate(file, AF_DEFAULT_TRACK);
	afGetVirtualSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat,
		&sampleWidth);

	if (sampleFormat == AF_SAMPFMT_UNSIGNED)
	{
		afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK,
			AF_SAMPFMT_TWOSCOMP, sampleWidth);
	}

	printf("frame count: %lld\n", frameCount);
	printf("frame size: %d bytes\n", (int) frameSize);
	printf("channel count: %d\n", channelCount);
	printf("sample rate: %.2f Hz\n", sampleRate);
	buffer = malloc(BUFFERED_FRAME_COUNT * frameSize);

	outportconfig = alNewConfig();
	setwidth(outportconfig, sampleWidth);
	setsampleformat(outportconfig, sampleFormat);
	alSetChannels(outportconfig, channelCount);

	count = afReadFrames(file, AF_DEFAULT_TRACK, buffer, BUFFERED_FRAME_COUNT);

	outport = alOpenPort("irixread", "w", outportconfig);
	setrate(outport, sampleRate);

	do
	{
		printf("count = %lld\n", count);
		alWriteFrames(outport, buffer, count);

		count = afReadFrames(file, AF_DEFAULT_TRACK, buffer,
			BUFFERED_FRAME_COUNT);
	} while (count > 0);

	waitport(outport);

	alClosePort(outport);
	alFreeConfig(outportconfig);

	afCloseFile(file);
}
Example #19
0
	Result process()
	{
		if (const YAML::Node *n = m_entry.FindValue(kSkip))
			return kSkipped;

		if (const YAML::Node *n = m_entry.FindValue(kPath))
		{
			n->GetScalar(m_path);
		}
		else
		{
			logerr("no path specified, line %d", n->GetMark().line);
			return kManifestError;
		}

		if (const YAML::Node *n = m_entry.FindValue(kMD5Sum))
		{
			std::string md5 = md5sum(m_path);
			std::string expectedMD5;
			n->GetScalar(expectedMD5);
			if (md5 != expectedMD5)
			{
				logerr("md5 checksum differs from expected value");
				return kFailure;
			}
		}

		AFfilehandle file = afOpenFile(m_path.c_str(), "r", NULL);

		if (const YAML::Node *n = m_entry.FindValue(kInvalid))
		{
			if (!file)
				return kSuccess;
			logerr("opening invalid file did not fail as expected");
			return kFailure;
		}

		if (!file)
		{
			logerr("could not open file");
			return kFailure;
		}

		for (YAML::Iterator i = m_entry.begin(); i != m_entry.end(); ++i)
		{
			std::string key = i.first().to<std::string>();
			std::string value = i.second().to<std::string>();

			if (key == kFileFormat)
			{
				const char *fileFormat =
					(const char *) afQueryPointer(AF_QUERYTYPE_FILEFMT,
						AF_QUERY_LABEL, afGetFileFormat(file, NULL), 0, 0);
				assert(fileFormat);
				expect(key, std::string(fileFormat), value);
			}
			else if (key == kChannels)
			{
				int expectedChannels = atoi(value.c_str());
				expect(key, expectedChannels,
					afGetChannels(file, AF_DEFAULT_TRACK));
			}
			else if (key == kByteOrder)
			{
				int expectedByteOrder;
				if (value == kByteOrder_Big)
					expectedByteOrder = AF_BYTEORDER_BIGENDIAN;
				else if (value == kByteOrder_Little)
					expectedByteOrder = AF_BYTEORDER_LITTLEENDIAN;
				else
				{
					logerr("bad value for byte order: %s, line %d",
						value.c_str(),
						i.second().GetMark().line);
					return kManifestError;
				}

				expect(key, expectedByteOrder,
					afGetByteOrder(file, AF_DEFAULT_TRACK));
			}
			else if (key == kSampleRate)
			{
				double expectedSampleRate = atof(value.c_str());

				expect(key, expectedSampleRate,
					afGetRate(file, AF_DEFAULT_TRACK));
			}
			else if (key == kSampleFormat)
			{
				std::string width = value.substr(1, value.length() - 1);
				char format = value[0];

				int expectedSampleWidth = atoi(width.c_str());
				bool isValidSampleWidth =
					(expectedSampleWidth >= 1 && expectedSampleWidth <= 32) ||
					expectedSampleWidth == 64;
				if (!isValidSampleWidth)
				{
					logerr("bad value for sample format: %s, line %d",
						value.c_str(), i.second().GetMark().line);
					return kManifestError;
				}

				int expectedSampleFormat = -1;
				switch (format)
				{
					case 's':
						expectedSampleFormat = AF_SAMPFMT_TWOSCOMP; break;
					case 'u':
						expectedSampleFormat = AF_SAMPFMT_UNSIGNED; break;
					case 'f':
						if (expectedSampleWidth == 32)
							expectedSampleFormat = AF_SAMPFMT_FLOAT;
						else if (expectedSampleWidth == 64)
							expectedSampleFormat = AF_SAMPFMT_DOUBLE;
						break;
					default:
						logerr("bad value for sample format: %s, line %d",
							value.c_str(), i.second().GetMark().line);
						return kManifestError;
				}

				int sampleFormat, sampleWidth;
				afGetSampleFormat(file, AF_DEFAULT_TRACK, &sampleFormat, &sampleWidth);
				expect(key, expectedSampleFormat, sampleFormat);
				expect(key, expectedSampleWidth, sampleWidth);
			}
			else if (key == kCompression)
			{
				int expectedCompression;
				if (value == kCompression_None)
					expectedCompression = AF_COMPRESSION_NONE;
				else if (value == kCompression_IMA_ADPCM)
					expectedCompression = AF_COMPRESSION_IMA;
				else if (value == kCompression_MS_ADPCM)
					expectedCompression = AF_COMPRESSION_MS_ADPCM;
				else if (value == kCompression_ulaw)
					expectedCompression = AF_COMPRESSION_G711_ULAW;
				else if (value == kCompression_alaw)
					expectedCompression = AF_COMPRESSION_G711_ALAW;
				else if (value == kCompression_FLAC)
					expectedCompression = AF_COMPRESSION_FLAC;
				else if (value == kCompression_ALAC)
					expectedCompression = AF_COMPRESSION_ALAC;
				else
				{
					logerr("bad value for compression: %s, line %d",
						value.c_str(), i.second().GetMark().line);
					return kManifestError;
				}

				expect(key, expectedCompression,
					afGetCompression(file, AF_DEFAULT_TRACK));
			}
			else if (key == kFrames)
			{
				AFframecount expectedFrameCount = atoll(value.c_str());
				expect(key, expectedFrameCount,
					afGetFrameCount(file, AF_DEFAULT_TRACK));

				int bufferFrameCount = 1024;
				int channels = afGetChannels(file, AF_DEFAULT_TRACK);
				int maxBytesPerFrame = 8;
				char *buffer = new char[channels * bufferFrameCount * maxBytesPerFrame];
				AFframecount framesRead = 0;
				while (framesRead < expectedFrameCount)
				{
					AFframecount framesToRead = std::min<AFframecount>(bufferFrameCount,
						expectedFrameCount - framesRead);
					AFframecount result = afReadFrames(file, AF_DEFAULT_TRACK,
						buffer, framesToRead);
					if (result != framesToRead)
					{
						m_failures++;
						break;
					}
					framesRead += result;
				}
				delete [] buffer;
			}
			else if (key == kBytes)
			{
				AFfileoffset expectedTrackBytes = atoll(value.c_str());
				expect(key, expectedTrackBytes,
					afGetTrackBytes(file, AF_DEFAULT_TRACK));
			}
		}

		afCloseFile(file);

		return m_failures == 0 ? kSuccess : kFailure;
	}