WaveModule extends ModuleBase { @Override public int parse(InputStream stream, RepInfo info, int parseIndex) { initParse(); info.setModule(this); _aesMetadata.setPrimaryIdentifier(info.getUri()); if (info.getURLFlag()) { _aesMetadata.setOtherPrimaryIdentifierType("URI"); } else { _aesMetadata.setPrimaryIdentifierType(AESAudioMetadata.FILE_NAME); } setupDataStream(stream, info); try { String firstFourChars = read4Chars(_dstream); if (firstFourChars.equals(RF64_SIGNATURE)) { info.setProfile("RF64"); flagRF64 = true; } else if (!firstFourChars.equals(RIFF_SIGNATURE)) { info.setMessage( new ErrorMessage(MessageConstants.WAVE_HUL_1, 0)); info.setWellFormed(false); return 0; } riffSize = readUnsignedInt(_dstream); String formType = read4Chars(_dstream); if (!"WAVE".equals(formType)) { info.setMessage(new ErrorMessage( MessageConstants.WAVE_HUL_2, _nByte - RIFF_FORM_TYPE_LENGTH)); info.setWellFormed(false); return 0; } info.setSigMatch(_name); info.setFormat(_format[0]); info.setMimeType(_mimeType[0]); if (flagRF64) { if (readChunk(info) && dataSize64ChunkSeen) { if (riffSize == LOOKUP_EXTENDED_DATA_SIZE) { if (Long.compareUnsigned(extendedRiffSize, Long.MAX_VALUE) > 0) { info.setMessage(new InfoMessage( MessageConstants.WAVE_HUL_22)); info.setWellFormed(RepInfo.UNDETERMINED); return 0; } } } else { info.setMessage(new ErrorMessage( MessageConstants.WAVE_HUL_23, Chunk.HEADER_LENGTH + RIFF_FORM_TYPE_LENGTH)); info.setWellFormed(false); return 0; } } while (getBytesRemaining() > 0) { if (!readChunk(info)) { break; } } if (getBytesRemaining() > 0) { remainingDataInfo(_dstream, info, getBytesRemaining(), firstFourChars); } } catch (EOFException eofe) { info.setWellFormed(false); String subMessage = String.format( MessageConstants.WAVE_HUL_3_SUB.getMessage(), getBytesRemaining()); if (eofe.getMessage() != null) { subMessage += "; " + eofe.getMessage(); } info.setMessage(new ErrorMessage(MessageConstants.WAVE_HUL_3, subMessage, _nByte)); } catch (Exception e) { e.printStackTrace(); info.setWellFormed(false); JhoveMessage message = JhoveMessages.getMessageInstance( MessageConstants.WAVE_HUL_4.getId(), String.format(MessageConstants.WAVE_HUL_4.getMessage(), e.getClass().getName() + ", " + e.getMessage())); info.setMessage(new ErrorMessage(message, _nByte)); return 0; } if (sampleCount > 0) { _aesMetadata.setDuration(sampleCount); } if (!_labels.isEmpty()) { _propList.add(new Property("Labels", PropertyType.PROPERTY, PropertyArity.LIST, _labels)); } if (!_labeledText.isEmpty()) { _propList.add(new Property("LabeledText", PropertyType.PROPERTY, PropertyArity.LIST, _labeledText)); } if (!_notes.isEmpty()) { _propList.add(new Property("Notes", PropertyType.PROPERTY, PropertyArity.LIST, _notes)); } if (!_samples.isEmpty()) { _propList.add(new Property("Samples", PropertyType.PROPERTY, PropertyArity.LIST, _samples)); } if (_exifInfo != null) { _propList.add(_exifInfo.buildProperty()); } if (!formatChunkSeen) { info.setMessage(new ErrorMessage(MessageConstants.WAVE_HUL_5)); info.setWellFormed(false); return 0; } if (!dataChunkSeen) { info.setMessage(new ErrorMessage(MessageConstants.WAVE_HUL_24)); info.setWellFormed(false); return 0; } if (_ckSummer != null) { skipDstreamToEnd(info); setChecksums(this._ckSummer, info); } info.setProperty(_metadata); if (flagPCMWaveFormat) { info.setProfile("PCMWAVEFORMAT"); } if (flagWaveFormatEx) { info.setProfile("WAVEFORMATEX"); } if (flagWaveFormatExtensible) { info.setProfile("WAVEFORMATEXTENSIBLE"); } if (broadcastExtChunkSeen && ( (waveCodec == FormatChunk.WAVE_FORMAT_MPEG && factChunkSeen) || waveCodec == FormatChunk.WAVE_FORMAT_PCM)) { info.setProfile("BWF"); } return 0; } WaveModule(); @Override int parse(InputStream stream, RepInfo info, int parseIndex); void markFirstSampleOffset(); void setExifInfo(ExifInfo exifInfo); void setBlockAlign(int align); ExifInfo getExifInfo(); int getWaveCodec(); int getBlockAlign(); void addWaveProperty(Property prop); void addLabel(Property p); void addLabeledText(Property p); void addSample(Property p); void addNote(Property p); void addListInfo(List l); long readSignedLong(DataInputStream stream); long readUnsignedInt(DataInputStream stream); int readSignedInt(DataInputStream stream); int readUnsignedShort(DataInputStream stream); int readSignedShort(DataInputStream stream); String read4Chars(DataInputStream stream); void setWaveCodec(int value); void addSamples(long samples); void setSampleRate(long rate); void setPCMWaveFormat(boolean b); void setWaveFormatEx(boolean b); void setWaveFormatExtensible(boolean b); AESAudioMetadata getAESMetadata(); Property buildBitmaskProperty(int val, String name,
			String[] oneValueNames, String[] zeroValueNames); boolean hasExtendedDataSizes(); void setExtendedRiffSize(long size); void setExtendedSampleLength(long length); long getExtendedSampleLength(); void addExtendedChunkSize(String chunkId, Long chunkSize); static final long LOOKUP_EXTENDED_DATA_SIZE; }
@Test public void testSample3() throws IOException { File f = new File("src/test/resources/wave/sample3.wav"); RepInfo info = new RepInfo(f.getName()); module.parse(new FileInputStream(f), info, 0); assertEquals("Should not be well formed. ", info.getWellFormed(), RepInfo.FALSE); assertTrue("There should be at least one message. ", info.getMessage() .size() > 0); boolean foundEofMessage = false; for( Message m : info.getMessage()) { if ("WAVE-HUL-3".equals(m.getId()) && m.getOffset() == 96) { foundEofMessage = true; } System.out.println("MESSAGE: (" + m.getId() + ") " + m.getMessage() + " " + m.getSubMessage() + " @" + m.getOffset()); } assertTrue("The message of id=WAVE-HUL-3 ('Unexpected end of file')@96 was not found. ", foundEofMessage); }