Esempio n. 1
0
// ----------------------------------------------------------------------------
//
void BeatDetector::attach( AudioInputStream* audio, unsigned frequency_bins ) {
    detach();

    m_audio_stream = audio;
    m_frequency_bins = frequency_bins;

    if ( audio ) {
        m_sample_size = m_audio_stream->getSampleSize();
        m_samples_per_second = m_audio_stream->getFormat().Format.nSamplesPerSec;

        STUDIO_ASSERT( m_frequency_bins <= m_sample_size/2, "Too many frequency bins" );		 // THROW ERROR
        STUDIO_ASSERT( m_frequency_bins > 0, "Too few frequency bins" );
        STUDIO_ASSERT( m_frequency_bins <= BEAT_DETECTOR_MASK_SIZE*32, "Too many beat detector frequency bins - %d requested", m_frequency_bins );

        for ( unsigned i=0; i < m_frequency_bins; i++ )
            m_bins.push_back( FreqBin( m_samples_per_second / m_sample_size, m_sensitivity_ms ) );

        m_B = new double[ m_sample_size ];
        m_Es = new double[ m_sample_size ];	

        // Reset all beat frequency bins
        for ( FreqBinArray::iterator it=m_bins.begin(); it != m_bins.end(); ++it )
            (*it).reset();

        m_audio_stream->addAudioProcessor( this, ProcessorFormat( 2, m_frequency_bins > 1 ) );
    }
}
// ----------------------------------------------------------------------------
// NOTE: Dimmer channel should contain 0 for full off and 255 for full on and
// no other values
//
void SceneMovementAnimatorTask::populateChannelAnimations(
    ParticipantArray& participants, size_t& particpant_index,
    AngleList& tilt, AngleList& pan, ChannelValueArray& dimmer,
    ChannelValueArray& speed, size_t group_size, bool run_once )
{
    size_t end = particpant_index + group_size;

    // If run once, add last entry to shut down the lights
    if ( run_once && dimmer.size() > 0 ) {
        dimmer.push_back( 0 );
    }

    ChannelAnimationStyle style( run_once ? CAM_LIST_ONCE : CAM_LIST );

    for ( ; particpant_index < end && particpant_index < participants.size(); particpant_index++ ) {
		channel_address pan_channel = participants[ particpant_index ].m_head.m_pan;
		channel_address tilt_channel = participants[ particpant_index ].m_head.m_tilt;
		channel_address dimmer_channel = participants[ particpant_index ].m_head.m_dimmer;
		channel_address speed_channel = participants[ particpant_index ].m_head.m_speed;
        UID actor_uid = participants[ particpant_index ].m_actor_uid;

        Fixture* pf = getActorRepresentative( actor_uid );
        if ( !pf )
            continue;

        if ( tilt_channel != INVALID_CHANNEL && tilt.size() ) {
            Channel* cp = pf->getChannel( tilt_channel );
            add( actor_uid, tilt_channel, style, anglesToValues( cp, tilt, cp->getMinAngle(), cp->getMaxAngle() ) );
        }

        if ( pan_channel != INVALID_CHANNEL && pan.size() ) {
            Channel* cp = pf->getChannel( pan_channel );
            add( actor_uid, pan_channel, style, anglesToValues( cp, pan, cp->getMinAngle(), cp->getMaxAngle() ) );
        }

        if ( speed_channel != INVALID_CHANNEL && speed.size() ) {
            add( actor_uid, speed_channel, style, speed );
        }

        if ( dimmer_channel != INVALID_CHANNEL && dimmer.size() ) {
            Channel* ch = pf->getChannel( dimmer_channel );
            STUDIO_ASSERT( ch, "Can't access dimmer channel %d on fixture %s", dimmer_channel, pf->getFullName() );

            BYTE low = ch->getDimmerLowestIntensity();
            BYTE high = ch->getDimmerHighestIntensity();

            // Replace all 255 dimmer high value with the fixture's dimmer value iff the actors value != 0
            SceneActor* actor = getActor( actor_uid );
            if ( actor && actor->getFinalChannelValue( pf->getUID(), dimmer_channel ) != 0 )
                high = actor->getFinalChannelValue( pf->getUID(), dimmer_channel );

            if ( low != 0 || high != 255 ) {                // Special case odd dimmer values
                for ( size_t i=0; i < dimmer.size(); i++ )
                    dimmer[i] = ( dimmer[i] == 255 ) ? high : low;
            }

            add( actor_uid, dimmer_channel, style, dimmer );
        }
    }
}
// ----------------------------------------------------------------------------
// Get master volume
//
void AudioVolumeController::setMasterVolume( UINT volume )
{
    STUDIO_ASSERT( volume >= 0 && volume <= 100, "Master volume value outside allowed range of 0-100" );

    HRESULT hr;

    hr = m_endpointVolume->SetMasterVolumeLevelScalar( static_cast<float>(volume) / 100.0F, NULL );
    AUDIO_VOLUME_ASSERT( hr, "Cannot set current volume" );
}
Esempio n. 4
0
// ----------------------------------------------------------------------------
//
void MusicPlayer::initialize( ) 
{
    m_library = LoadLibrary( m_dll_path );
    STUDIO_ASSERT( m_library, "Unable to load music controller DLL '%s'", m_dll_path );

    GetPlayerApiVersion pGetPlayerApiVersion = getAddress<GetPlayerApiVersion>( "GetPlayerApiVersion" );
    STUDIO_ASSERT( (*pGetPlayerApiVersion)() == 2, "Music controller version is not compatible" );

    m_GetPlayerInfo = getAddress<GetPlayerInfo>( "GetPlayerInfo" );
    m_Connect = getAddress<Connect>( "Connect" );
    m_Disconnect = getAddress<Disconnect>( "Disconnect" );
    m_RegisterEventListener = getAddress<RegisterEventListener>( "RegisterEventListener" );
    m_UnregisterEventListener = getAddress<UnregisterEventListener>( "UnregisterEventListener" );
    m_Signon = getAddress<Signon>( "Signon" );
	m_AcceptAuthorization = getAddress<AcceptAuthorization>( "AcceptAuthorization" );
	m_IsLoggedIn = getAddress<IsLoggedIn>( "IsLoggedIn" );

    m_GetPlaylists = getAddress<GetPlaylists>( "GetPlaylists" );
    m_GetPlaylistInfo = getAddress<GetPlaylistInfo>( "GetPlaylistInfo" );
    m_GetTracks = getAddress<GetTracks>( "GetTracks" );
	m_SearchTracks = getAddress<SearchTracks>( "SearchTracks" );
    m_QueueTrack = getAddress<QueueTrack>( "QueueTrack" );
    m_PlayTrack = getAddress<PlayTrack>( "PlayTrack" );
    m_PlayAllTracks = getAddress<PlayAllTracks>( "PlayAllTracks" );
    m_ForwardTrack = getAddress<ForwardTrack>( "ForwardTrack" );
    m_BackTrack = getAddress<BackTrack>( "BackTrack" );
    m_StopTrack = getAddress<StopTrack>( "StopTrack" );
    m_PauseTrack = getAddress<PauseTrack>( "PauseTrack" );
    m_GetPlayingTrack = getAddress<GetPlayingTrack>( "GetPlayingTrack" );
    m_IsTrackPaused = getAddress<IsTrackPaused>( "IsTrackPaused" );
    m_GetTrackInfo = getAddress<GetTrackInfo>( "GetTrackInfo" );
    m_GetTrackAudioInfo = getAddress<GetTrackAudioInfo>( "GetTrackAudioInfo" );
    m_GetQueuedTracks = getAddress<GetQueuedTracks>( "GetQueuedTracks" );
    m_GetPlayedTracks = getAddress<GetPlayedTracks>( "GetPlayedTracks" );
    m_GetLastPlayerError = getAddress<GetLastPlayerError>( "GetLastPlayerError" );
    m_WaitOnTrackEvent = getAddress<WaitOnTrackEvent>( "WaitOnTrackEvent" );
    m_GetTrackAnalysis = getAddress<GetTrackAnalysis>( "GetTrackAnalysis" );

	getPlayerInfo( &m_player_info );
}
// ----------------------------------------------------------------------------
//
ChannelValueArray SceneMovementAnimatorTask::anglesToValues( Channel* channel, AngleList& angles, UINT min_angle, UINT max_angle )
{
    ChannelValueArray values;

    for ( UINT angle : angles ) {
        if ( angle < min_angle )
            angle = min_angle;
        else if ( angle > max_angle )
            angle = max_angle;

        values.push_back( channel->convertAngleToValue( angle ) );
    }

    STUDIO_ASSERT( values.size() > 0, "Invalid angles array size" );
    return values;
}
Esempio n. 6
0
// ----------------------------------------------------------------------------
//
Scene* VenueReader::read( TiXmlElement* self, Scene* scene )
{
    scene = new Scene();

    readDObject( self, scene, "scene_number" );

    scene->m_bpm_rating = (BPMRating)read_int_attribute( self, "bpm_rating", BPMRating::BPM_NO_RATING);

    std::vector<SceneActor *> actors = 
        read_xml_list<SceneActor>( self->FirstChildElement( "actors" ), "actor" );

    for ( std::vector<SceneActor *>::iterator it=actors.begin(); it != actors.end(); ++it ) {
        scene->addActor( *(*it) );
        delete (*it);
    }

    TiXmlElement* acts = self->FirstChildElement( "acts" );
    if ( acts ) {
        TiXmlElement* element = acts->FirstChildElement( "act" );
        while ( element ) {
            scene->m_acts.insert( read_unsigned_attribute( element, "number" ) ) ;
            element = element->NextSiblingElement();
        }
    }

    TiXmlElement* container = self->FirstChildElement( "animations" );
    if ( container ) {
        TiXmlElement* element = container->FirstChildElement( "animation" );
        while ( element ) {
            const char* class_name = read_text_attribute( element, "class" );
            AbstractAnimation* animation = NULL;

            if ( !strcmp( class_name, SceneSequence::className ) )
                animation = read( element, (SceneSequence*)NULL );
            else if ( !strcmp( class_name, SceneSoundLevel::className ) )
                animation = read( element, (SceneSoundLevel*)NULL );
            else if ( !strcmp( class_name, SceneChannelAnimator::className ) )
                animation = read( element, (SceneChannelAnimator*)NULL );
            else if ( !strcmp( class_name, ScenePatternDimmer::className ) )
                animation = read( element, (ScenePatternDimmer*)NULL );
            else if ( !strcmp( class_name, SceneColorFader::className ) )
                animation = read( element, (SceneColorFader*)NULL );
            else if ( !strcmp( class_name, SceneMovementAnimator::className ) )
                animation = read( element, (SceneMovementAnimator*)NULL );
            else if ( !strcmp( class_name, SceneStrobeAnimator::className ) )
                animation = read( element, (SceneStrobeAnimator*)NULL );
            else if ( !strcmp( class_name, ScenePixelAnimator::className ) )
                animation = read( element, (ScenePixelAnimator*)NULL );
            else if ( !strcmp( class_name, SceneChannelFilter::className ) )
                animation = read( element, (SceneChannelFilter*)NULL );
            else
                STUDIO_ASSERT( false, "Unknown animation class '%s'", class_name );

            scene->addAnimation( animation );

            element = element->NextSiblingElement();
        }
    }

    return scene;
}
Esempio n. 7
0
// ----------------------------------------------------------------------------
//
Channel* DefinitionReader::read( TiXmlElement* self, Channel* channel )
{
    channel = new Channel();

    try {
        channel->m_channel_offset = (channel_t)read_dword_attribute( self, "index" );
        channel->m_type = Channel::convertTextToChannelType( read_text_attribute( self, "type" ) );
        channel->m_name = read_text_element( self, "name" );
        channel->m_is_color = read_bool_attribute( self, "color" );
        channel->m_can_blackout = read_bool_attribute( self, "blackout" );
        channel->m_can_whiteout = read_bool_attribute( self, "whiteout", true );
        channel->m_default_value = (BYTE)read_int_attribute( self, "value" );
        channel->m_home_value = (BYTE)read_int_attribute( self, "home_value" );
        channel->m_pixel_index = (BYTE)read_int_attribute( self, "pixel" );
        channel->m_head_number = (BYTE)read_int_attribute( self, "head" );

        // If head number is not set on tilt or pan, default to 1
        if ( channel->m_head_number == 0 && 
             (channel->m_type == CHNLT_TILT
              || channel->m_type == CHNLT_PAN
              || channel->m_type == CHNLT_PAN_FINE
              || channel->m_type == CHNLT_TILT_FINE) )
            channel->m_head_number = 1;

        STUDIO_ASSERT( channel->m_channel_offset > 0, "Channel '%s' index < 1", channel->m_name );

        channel->m_channel_offset--;        // Adjust offset for internal zero based

        TiXmlElement *dimmer = self->FirstChildElement( "dimmer" );
        if ( dimmer ) {
            channel->m_is_dimmer = true;
            channel->m_lowest_intensity = (BYTE)read_int_attribute( dimmer, "lowest_intensity", 0 );
            channel->m_highest_intensity = (BYTE)read_int_attribute( dimmer, "highest_intensity", 255 );
        }
        else {
            channel->m_is_dimmer = ( channel->m_type == CHNLT_DIMMER );     // Implies this is the default 0-255 dimmer channel type
            channel->m_lowest_intensity = 0;
            channel->m_highest_intensity = 255;
        }

        // Add channel ranges
        std::vector<ChannelValueRange *> ranges = 
            read_xml_list<ChannelValueRange>( self->FirstChildElement( "ranges" ), "range" );

        for ( std::vector<ChannelValueRange *>::iterator it=ranges.begin(); it != ranges.end(); ++it ) {
            STUDIO_ASSERT( (*it)->getEnd() >= (*it)->getStart(), "Channel '%s' range %s invalid", channel->m_name, (*it)->getName() );
            STUDIO_ASSERT( channel->getRange( (*it)->getEnd() ) == NULL, "Channel '%s' range %s overlaps", channel->m_name, (*it)->getName() );
            STUDIO_ASSERT( channel->getRange( (*it)->getStart() ) == NULL, "Channel '%s' range %s overlaps", channel->m_name, (*it)->getName() );
            channel->m_ranges.push_back( *(*it) );
            delete (*it);
        }

        // Add angles
        std::vector<ChannelAngle *> angles = 
            read_xml_list<ChannelAngle>( self->FirstChildElement( "angles" ), "angle" );

        for ( std::vector<ChannelAngle *>::iterator it=angles.begin(); it != angles.end(); ++it ) {
            channel->m_angles[ (*it)->getAngle() ] = *(*it);
            delete (*it);
        }

        channel->generateAngleTable();
    }
    catch( ... ) {
        delete channel;
        throw;
    }

    return channel;
}
// ----------------------------------------------------------------------------
//
void SceneMovementAnimatorTask::generateProgram( AnimationDefinition* definition )
{
    SceneMovementAnimator* config = dynamic_cast< SceneMovementAnimator *>( definition );

    MovementAnimation& movement = config->movement();

    ParticipantArray participants;
    Head head;

    // Determine which actors will be participating
	for ( SceneActor& actor : getActors() ) {
        Fixture* pf = getActorRepresentative( actor.getActorUID() );
        if ( !pf || !pf->canMove() )
            continue;

        if ( movement.m_head_number == 0 ) { // All heads on fixture(s)
            for ( UINT head_number=1; head_number <= pf->getNumHeads(); head_number++ ) {
                if ( pf->getHead( head_number, head ) )
                    participants.emplace_back( actor.getActorUID(), head );                    
            }
        }
        else {                                 // Single head on fixture(s)
            if ( pf->getHead( movement.m_head_number, head ) )
                participants.emplace_back( actor.getActorUID(), head ); 
        }
    }

    STUDIO_ASSERT( movement.m_group_size >= 1, "Movement group size must be >= 1" );
    STUDIO_ASSERT( movement.m_home_wait_periods > 0 && movement.m_home_wait_periods < MAX_WAIT_PERIODS, 
        "Home wait periods must be between 1 and %d", MAX_WAIT_PERIODS );
    STUDIO_ASSERT( movement.m_dest_wait_periods > 0 && movement.m_dest_wait_periods < MAX_WAIT_PERIODS, 
        "Destination wait periods must be between 1 and %d", MAX_WAIT_PERIODS );

    // TODO: At some point, pre-compute the channel arrays once rather on each scene load as
    // that will be a problem for many fixtures/animations in a single scene.

    switch ( movement.m_movement_type ) {
        case MOVEMENT_RANDOM:							// Move to random locations
            genRandomMovement( movement, participants );
            break;

        case MOVEMENT_FAN:								// Fan beams
            genFanMovement( movement, participants );
            break;

        case MOVEMENT_ROTATE:							// Simple rotate at tilt angle
            genRotateMovement( movement, participants );
            break;

        case MOVEMENT_NOD:								// Simple up and down
            genNodMovement( movement, participants );
            break;

        case MOVEMENT_XCROSS:							// Cross fixture beams
            genXcrossMovement( movement, participants );
            break;

        case MOVEMENT_MOONFLOWER:						// Moonflower effect
            genMoonflowerMovement( movement, participants );
            break;

        case MOVEMENT_COORDINATES:						// Absolute coordinates effect
            genCoordinatesMovement( movement, participants );
            break;

        case MOVEMENT_SINEWAVE:						    // Sinewave movement
            genSineMovement( movement, participants );
            break;
    }
}
// ----------------------------------------------------------------------------
//
void SceneMovementAnimatorTask::genMoonflowerMovement( MovementAnimation& movement, ParticipantArray& participants )
{
    STUDIO_ASSERT( movement.m_height > 0, "Height must be a positive integer > 0" );
    if ( participants.size() == 0 )
        return;

    double fixture_angle_increment = 360 / participants.size();
    double start_angle = 0;

    for ( size_t particpant_index=0; particpant_index < participants.size(); ) {
        AngleList pan;
        AngleList tilt;
        ChannelValueArray dimmer;
        ChannelValueArray speed;

        UINT pan_start;
        UINT tilt_start;

        compute_pan_tilt( particpant_index, movement.m_height, movement.m_fixture_spacing, 
            movement.m_home_x, movement.m_home_y, pan_start, tilt_start );

        double angle = start_angle;

        for ( size_t i=0; i < movement.m_positions; i++ ) {
            // Go home
            tilt.push_back( tilt_start );
            pan.push_back( pan_start );

            double target_x = movement.m_home_x + movement.m_radius * cos( angle * 180 / M_PI );
            double target_y = movement.m_home_y + movement.m_radius * sin( angle * 180 / M_PI );

            //printf( "fixture %d: %f,%f to x,y=%f,%f angle=%f\n", particpant_index, home_x, home_y, target_x, target_y, angle );

            UINT pan_target;
            UINT tilt_target;

            compute_pan_tilt( particpant_index, movement.m_height, movement.m_fixture_spacing, 
                target_x, target_y, pan_target, tilt_target );

            //printf( "%d: pan_start=%d tilt_start=%d pan_end=%d tilt_end=%d\n", particpant_index, pan_start, tilt_start, pan_target, tilt_target);

            compute_fastest_path( pan_start, tilt_start, pan_target, tilt_target );

            //printf( "%d: pan_start=%d tilt_start=%d pan_end=%d tilt_end=%d\n", particpant_index, pan_start, tilt_start, pan_target, tilt_target);

            // Go to destination
            for ( UINT i=0; i < movement.m_dest_wait_periods; i++ ) {
                tilt.push_back( tilt_target );
                pan.push_back( pan_target );
            }

            // Go back home
            for ( UINT i=0; i < movement.m_home_wait_periods-1; i++ ) {
                tilt.push_back( tilt_start );
                pan.push_back( pan_start );
            }

            angle += movement.m_pan_increment;
            if ( angle > 360 ) 
                angle -= 360;
        }

        populateChannelAnimations( participants, particpant_index, tilt, pan, dimmer, speed, 1, movement.m_run_once );

        start_angle += fixture_angle_increment;
    }
}
void SceneMovementAnimatorTask::genRandomMovement( MovementAnimation& movement, ParticipantArray& participants )
{
    STUDIO_ASSERT( movement.m_positions > 0 && movement.m_positions < MAX_RANDOM_POSITIONS, 
        "Random postions should be between 1 and %d", MAX_RANDOM_POSITIONS );

    for ( size_t particpant_index=0; particpant_index < participants.size(); ) {
        Fixture* pf = getActorRepresentative( participants[ particpant_index ].m_actor_uid );
        if ( !pf )
            continue;

        UINT tilt_start = movement.m_tilt_start, tilt_end = movement.m_tilt_end;
        UINT pan_start = movement.m_pan_start, pan_end = movement.m_pan_end;

        AngleList pan;
        AngleList tilt;
        ChannelValueArray dimmer;
        ChannelValueArray speed;

        channel_address tilt_channel = participants[ particpant_index ].m_head.m_tilt;
        if ( tilt_channel != INVALID_CHANNEL ) {
            Channel* cp = pf->getChannel( tilt_channel );
            tilt_start = std::max<UINT>( tilt_start, cp->getMinAngle() );
            tilt_end = std::min<UINT>( tilt_end, cp->getMaxAngle() );
        }

        channel_address pan_channel = participants[ particpant_index ].m_head.m_pan;
        if ( pan_channel != INVALID_CHANNEL ) {
            Channel* cp = pf->getChannel( pan_channel );
            pan_start = std::max<UINT>( pan_start, cp->getMinAngle() );
            pan_end = std::min<UINT>( pan_end, cp->getMaxAngle() );
        }

        // Generate random locations within the tilt and pan bounds
        for ( UINT generate=0; generate < movement.m_positions; generate++ ) {
            UINT tilt_angle = random_angle( tilt_start, tilt_end );
            UINT pan_angle = random_angle( pan_start, pan_end );

            UINT wait_periods = movement.m_dest_wait_periods;

            // No light during movement
            if ( movement.m_backout_home_return && wait_periods > 1 ) {
                pan.push_back( pan_angle );
                tilt.push_back( tilt_angle );
                speed.push_back( 0 );
                dimmer.push_back( 0 );
                wait_periods--;
            }

            for ( UINT wait=0; wait < wait_periods; wait++ ) {
                pan.push_back( pan_angle );
                tilt.push_back( tilt_angle );
                speed.push_back( movement.m_speed );
                dimmer.push_back( 255 );
            }
        }

        if ( !movement.m_backout_home_return )          // TEMP fix for dimmer channel contention
            dimmer.clear();

        // Populate the channel arrays for the next group of fixtures
        populateChannelAnimations( participants, particpant_index, tilt, pan, dimmer, speed, movement.m_group_size, movement.m_run_once );
    }
}