package org.jactr.modules.pm.aural.memory.impl; /* * default logging */ import java.util.Collection; import java.util.Iterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.commonreality.agents.IAgent; import org.jactr.core.buffer.six.IStatusBuffer; import org.jactr.core.chunk.IChunk; import org.jactr.core.chunk.ISymbolicChunk; import org.jactr.core.chunk.IllegalChunkStateException; import org.jactr.core.logging.IMessageBuilder; import org.jactr.core.logging.Logger; import org.jactr.core.production.request.ChunkTypeRequest; import org.jactr.core.slot.IMutableSlot; import org.jactr.core.slot.ISlot; import org.jactr.core.utils.parameter.ParameterHandler; import org.jactr.modules.pm.aural.IAuralModule; import org.jactr.modules.pm.aural.memory.IAuralMemory; import org.jactr.modules.pm.aural.memory.impl.encoder.DigitAuralEncoder; import org.jactr.modules.pm.aural.memory.impl.encoder.SpeechAuralEncoder; import org.jactr.modules.pm.aural.memory.impl.encoder.ToneAuralEncoder; import org.jactr.modules.pm.aural.memory.impl.encoder.WordAuralEncoder; import org.jactr.modules.pm.aural.memory.impl.filter.AttendedAudioEventFilter; import org.jactr.modules.pm.aural.memory.impl.map.AudibleFeatureMap; import org.jactr.modules.pm.aural.memory.impl.map.DurationFeatureMap; import org.jactr.modules.pm.aural.memory.impl.map.FINSTAuralFeatureMap; import org.jactr.modules.pm.aural.memory.impl.map.KindFeatureMap; import org.jactr.modules.pm.aural.memory.impl.map.OffsetFeatureMap; import org.jactr.modules.pm.aural.memory.impl.map.OnsetFeatureMap; import org.jactr.modules.pm.common.memory.IActivePerceptListener; import org.jactr.modules.pm.common.memory.IPerceptualEncoder; import org.jactr.modules.pm.common.memory.PerceptualSearchResult; import org.jactr.modules.pm.common.memory.filter.IIndexFilter; import org.jactr.modules.pm.common.memory.filter.NumericIndexFilter; import org.jactr.modules.pm.common.memory.impl.AbstractPerceptualMemory; import org.jactr.modules.pm.common.memory.impl.DelayableAfferentObjectListener; import org.jactr.modules.pm.common.memory.map.IFeatureMap; public class DefaultAuralMemory extends AbstractPerceptualMemory implements IAuralMemory { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(DefaultAuralMemory.class); private IChunk _notAvailableChunk; public DefaultAuralMemory(IAuralModule module, IActivePerceptListener listener) { super(module, new AuralEventIndexManager(module)); // addListener(listener, ExecutorServices.INLINE_EXECUTOR); addFilter(new NumericIndexFilter(IAuralModule.ONSET_SLOT, true)); addFilter(new NumericIndexFilter(IAuralModule.OFFSET_SLOT, true)); addFilter(new NumericIndexFilter(IAuralModule.PITCH_SLOT, true)); addFilter(new NumericIndexFilter(IAuralModule.AZIMUTH_SLOT, true)); addFilter(new NumericIndexFilter(IAuralModule.ELEVATION_SLOT, true)); addFilter(new AttendedAudioEventFilter()); addFeatureMap(new OnsetFeatureMap()); addFeatureMap(new OffsetFeatureMap()); addFeatureMap(new KindFeatureMap()); addFeatureMap(new DurationFeatureMap()); addFeatureMap(new AudibleFeatureMap()); addFeatureMap(new FINSTAuralFeatureMap(module.getModel())); addEncoder(new SpeechAuralEncoder()); addEncoder(new ToneAuralEncoder()); addEncoder(new WordAuralEncoder()); addEncoder(new DigitAuralEncoder()); } public IAuralModule getAuralModule() { return (IAuralModule) getModule(); } @Override public void attach(IAgent agent) { super.attach(agent); ((DelayableAfferentObjectListener) getAfferentObjectListener()) .setPerceptualDelay(getAuralModule().getAuralDecayTime()); ((AuralEventIndexManager) getIndexManager()) .attach(getAfferentObjectListener()); try { _notAvailableChunk = getModule().getModel().getDeclarativeModule() .getChunk(IStatusBuffer.ERROR_NO_LONGER_AVAILABLE_CHUNK).get(); } catch (Exception e) { LOGGER.error("Could not get no-longer available chunk ", e); _notAvailableChunk = getModule().getModel().getDeclarativeModule() .getErrorChunk(); } } @Override public void detach() { ((AuralEventIndexManager) getIndexManager()) .detach(getAfferentObjectListener()); super.detach(); } @Override protected void fillIndexChunk(IChunk indexChunk, IChunk encodedChunk, ChunkTypeRequest originalRequest, ChunkTypeRequest expandedRequest) { try { indexChunk.getWriteLock().lock(); /* * now we just copy everything over, if possible */ ISymbolicChunk sc = indexChunk.getSymbolicChunk(); for (ISlot slot : expandedRequest.getSlots()) try { Object value = slot.getValue(); String name = slot.getName(); if (LOGGER.isDebugEnabled()) LOGGER.debug("Setting " + indexChunk + "." + name + "=" + value); ((IMutableSlot) sc.getSlot(name)).setValue(value); } catch (IllegalChunkStateException e) { // if the slot was a metaslot there will be an exception } } finally { indexChunk.getWriteLock().unlock(); } } @Override protected boolean isAcceptable(IChunk encodedChunk, ChunkTypeRequest originalRequest) { return encodedChunk.getSymbolicChunk().getChunkType().isA( getAuralModule().getSoundChunkType()); } @Override public void setParameter(String key, String value) { if (key.indexOf('.') > 0) { /* * might be a class */ if (LOGGER.isDebugEnabled()) LOGGER.debug("Assuming " + key + " is a classname"); try { boolean shouldAdd = ParameterHandler.booleanInstance().coerce(value) .booleanValue(); Class clazz = ParameterHandler.classInstance().coerce(key); if (!shouldAdd) { for (IIndexFilter filter : getFilters(null)) if (filter.getClass().getName().equals(key)) removeFilter(filter); for (IPerceptualEncoder encoder : getEncoders(null)) if (encoder.getClass().getName().equals(key)) removeEncoder(encoder); for (IFeatureMap map : getFeatureMaps(null)) if (map.getClass().getName().equals(key)) removeFeatureMap(map); } else { Object instance = clazz.newInstance(); if (instance instanceof IIndexFilter) addFilter((IIndexFilter) instance); if (instance instanceof IFeatureMap) addFeatureMap((IFeatureMap) instance); if (instance instanceof IPerceptualEncoder) addEncoder((IPerceptualEncoder) instance); } } catch (Exception e) { if (LOGGER.isWarnEnabled()) LOGGER.warn("Could not process suspected class name " + key + " = " + value, e); } } else super.setParameter(key, value); } @Override protected IChunk getRemovedErrorCodeChunk() { return _notAvailableChunk; } @Override protected PerceptualSearchResult select( Collection<PerceptualSearchResult> results) { IMessageBuilder mb = null; if (Logger.hasLoggers(getModule().getModel())) { mb = Logger.messageBuilder(); IMessageBuilder fmb = mb; mb.append("Aural search candidates :"); results.forEach( (psr) -> { fmb.append("["); fmb.append(psr.getPercept().getSymbolicChunk().getName()); fmb.append(" @ ") .append( psr.getLocation().getSymbolicChunk().getName()); fmb.append("] "); }); } if (LOGGER.isDebugEnabled()) LOGGER.debug("All results : " + results); PerceptualSearchResult rtn = null; if (results.size() > 0) { // grab one at random Iterator<PerceptualSearchResult> itr = results.iterator(); int which = (int) Math.floor(Math.random() * results.size()); if (mb != null) mb.prepend(String.format("Selecting %d", which)); for (int i = 0; i <= which && itr.hasNext(); i++) rtn = itr.next(); } if (LOGGER.isDebugEnabled()) LOGGER.debug(String.format("Selected : [%s]=[%s]", rtn != null ? rtn.getLocation() : "null", rtn)); if (mb != null) Logger.log(getModule().getModel(), Logger.Stream.AURAL, mb); return rtn; } }