Esempio n. 1
0
	/*! DRAGONS: We use the current UTF16String SetString trait to ensure that we always have the correct handling,
	 *           even if the user wants these strings handled differently (i.e. we do it their way!)
	 */
	void SetStringArray(MDObjectPtr &Array, const std::list<std::string> &Strings)
	{
		// Abort if we are send a NULL pointer
		if(!Array) return;

		// Don't bother if we have nothing to do
		if(Strings.empty()) return;

		// Build a working string
		static MDTypePtr ValType = MDType::Find("UTF16String");
		MDObjectPtr Value = ValType ? new MDObject(ValType) : NULL;
		if(!Value)
		{
			error("Can't build UTF16String value required by SetStringArray() - need this type to be defined in the dictionary file\n");
			return;
		}

		// Get a buffer in which to build the final string array, make it quite granular as it will keep growing
		DataChunkPtr Buffer = new DataChunk();
		Buffer->SetGranularity(16 * 1024);

		std::list<std::string>::const_iterator it = Strings.begin();
		while(it != Strings.end())
		{
			Value->SetString(*it);
			DataChunkPtr ThisString = Value->PutData();
			Buffer->Append(ThisString);
			
			// Add terminator if required, i.e. if the sub-string we just added did not end in a zero
			UInt8 *p = &ThisString->Data[ThisString->Size];

			// Terminate if either of the last two bytes in the current buffer is non-zero - or if the string was too short to have a terminator
			if((ThisString->Size) < 2 || ((*(--p) != 0) || (*(--p) != 0)))
			{
				const UInt8 Term[2] = { 0, 0};
				Buffer->Set(2, Term, Buffer->Size);
			}

			it++;
		}

		// Set the value from this buffer
		Array->SetValue(Buffer);
	}
Esempio n. 2
0
/*! \note This call will modify properties SampleRate, DataStart and DataSize */
MDObjectPtr mxflib::WAVE_PCM_EssenceSubParser::BuildWaveAudioDescriptor(FileHandle InFile, UInt64 Start /*=0*/)
{
	const unsigned int ID_RIFF = 0x52494646;		//! "RIFF"
	const unsigned int ID_fmt  = 0x666d7420;		//! "fmt "
	const unsigned int ID_data = 0x64617461;		//! "data"

	MDObjectPtr Ret;

	FileSeek(InFile, Start);
	U32Pair Header = ReadRIFFHeader(InFile);

	// Can't build a descriptor if it isn't a RIFF file!
	if(Header.first != ID_RIFF) return Ret;
	if(Header.second < 4) return Ret;

	// Read the RIFF file type (always 4 bytes)
	DataChunkPtr ChunkData = FileReadChunk(InFile, 4);
	
	// Can't build a descriptor if it isn't a WAVE file!
	if(memcmp(ChunkData->Data, "WAVE", 4) != 0) return Ret;

	// Scan the chunks within the RIFF file
	// DRAGONS: To do this properly we would check the file size in the RIFF chunk
	// DRAGONS: "LIST" chunks are "sets" and are not yet supported
	for(;;)
	{
		Header = ReadRIFFHeader(InFile);

		// End of file?
		if((Header.first == 0) && (Header.second == 0)) break;

		if(Header.first == ID_fmt)
		{
			ChunkData = FileReadChunk(InFile, Header.second);
			if(ChunkData->Size < 16) return Ret;

			UInt16 AudioFormat = GetU16_LE(&ChunkData->Data[0]);
			if(AudioFormat != 1) return Ret;

			Ret = new MDObject(WaveAudioDescriptor_UL);
			if(!Ret) return Ret;

			// Set the sample rate
			char Buffer[32];
			SampleRate = GetU32_LE(&ChunkData->Data[4]);
			sprintf(Buffer, "%d/1", SampleRate);
			Ret->SetString(SampleRate_UL, Buffer);
			Ret->SetString(AudioSamplingRate_UL, Buffer);

			// Must assume not locked!
			Ret->SetUInt(Locked_UL, 0);

			// Set channel count
			UInt16 Chan = GetU16_LE(&ChunkData->Data[2]);
			Ret->SetUInt(ChannelCount_UL, Chan);

			// Set quantization bits
			UInt16 Quant = GetU16_LE(&ChunkData->Data[14]);
			Ret->SetUInt(QuantizationBits_UL, Quant);

			// Calculate the number of bytes per sample
			SampleSize = ((Quant+7) / 8) * Chan;

			// Set the block alignment
			Ret->SetUInt(BlockAlign_UL, GetU16_LE(&ChunkData->Data[12]));

			// Set the byte-rate
			Ret->SetUInt(AvgBps_UL, GetU32_LE(&ChunkData->Data[8]));
		}
		else if(Header.first == ID_data)
		{
			// Record the location of the audio data
			DataStart = FileTell(InFile);
			DataSize = Header.second;

			// ...and skip the chunk value
			FileSeek(InFile, FileTell(InFile) + Header.second);
		}
		else
		{
			// Skip the chunk value
			FileSeek(InFile, FileTell(InFile) + Header.second);
		}
	}

	return Ret;
}